├── .github
└── workflows
│ ├── deploy.yml
│ └── library unit test.yml
├── .gitignore
├── .idea
├── .gitignore
├── kotlinc.xml
├── misc.xml
└── vcs.xml
├── LICENSE
├── README.md
├── build.gradle.kts
├── docs
├── images
│ ├── logo.png
│ └── telegram.svg
└── languages
│ └── README-en.md
├── gradle.properties
├── gradle
├── libs.versions.toml
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── library
├── build.gradle.kts
└── src
│ ├── androidMain
│ └── kotlin
│ │ └── more
│ │ └── math
│ │ ├── native
│ │ └── model
│ │ │ └── NativeProvider.android.kt
│ │ └── platform
│ │ └── model
│ │ ├── BigFloat.android.kt
│ │ └── BigInt.android.kt
│ ├── androidTest
│ └── java
│ │ └── more
│ │ └── math
│ │ └── native
│ │ └── model
│ │ └── NativeLibTest.kt
│ ├── androidUnitTest
│ └── kotlin
│ │ ├── more.math
│ │ └── MoreMathTest.kt
│ │ └── more
│ │ └── math
│ │ └── platform
│ │ └── model
│ │ └── Factorial_androidKtTest.kt
│ ├── commonMain
│ ├── cpp
│ │ ├── CMakeLists.txt
│ │ ├── hyperoperator.cpp
│ │ ├── hyperoperator.h
│ │ └── nativelib.cpp
│ └── kotlin
│ │ └── more
│ │ └── math
│ │ ├── Annotations.kt
│ │ ├── Extensions.kt
│ │ ├── MoreMath.kt
│ │ ├── combinatorics
│ │ └── CombinatoricsParent.kt
│ │ ├── complex
│ │ └── model
│ │ │ └── Complex.kt
│ │ ├── factorial
│ │ └── FactorialParent.kt
│ │ ├── graph
│ │ ├── model
│ │ │ ├── Connection.kt
│ │ │ ├── Graph.kt
│ │ │ ├── GraphPath.kt
│ │ │ ├── Vertex.kt
│ │ │ ├── exception
│ │ │ │ ├── NegativeWeightException.kt
│ │ │ │ └── VertexNotFoundException.kt
│ │ │ └── mode
│ │ │ │ ├── GraphMode.kt
│ │ │ │ ├── RemoveVertexMode.kt
│ │ │ │ └── SetVertexMode.kt
│ │ └── parent
│ │ │ └── GraphParent.kt
│ │ ├── matrix
│ │ ├── model
│ │ │ ├── Matrix.kt
│ │ │ ├── MatrixExtension.kt
│ │ │ └── MatrixSize.kt
│ │ └── parent
│ │ │ └── MatrixParent.kt
│ │ ├── native
│ │ └── model
│ │ │ └── NativeProvider.kt
│ │ ├── platform
│ │ └── model
│ │ │ ├── BigFloat.kt
│ │ │ └── BigInt.kt
│ │ ├── tetraction
│ │ └── TetractionParent.kt
│ │ └── vector
│ │ └── model
│ │ ├── Vector2.kt
│ │ └── Vector2Extensions.kt
│ ├── commonTest
│ └── kotlin
│ │ └── more
│ │ └── math
│ │ ├── ExtensionsKtTest.kt
│ │ ├── combinatorics
│ │ └── CombinatoricsTest.kt
│ │ ├── complex
│ │ └── model
│ │ │ └── ComplexTest.kt
│ │ ├── factorial
│ │ └── FactorialTest.kt
│ │ ├── graph
│ │ └── model
│ │ │ └── GraphTest.kt
│ │ ├── matrix
│ │ └── model
│ │ │ └── MatrixExtensionKtTest.kt
│ │ ├── other
│ │ └── OtherTest.kt
│ │ ├── platform
│ │ └── MoreMathPlatformSpecificTest.kt
│ │ ├── tetraction
│ │ └── TetractionTest.kt
│ │ └── vector
│ │ └── model
│ │ └── Vector2Test.kt
│ ├── iosMain
│ └── kotlin
│ │ └── more
│ │ └── math
│ │ ├── native
│ │ └── model
│ │ │ └── NativeProvider.ios.kt
│ │ └── platform
│ │ └── model
│ │ ├── BigFloat.ios.kt
│ │ └── BigInt.ios.kt
│ ├── iosTest
│ └── kotlin
│ │ └── more
│ │ └── math
│ │ ├── MoreMathTest.kt
│ │ └── platform
│ │ └── model
│ │ └── Factorial_iosKtTest.kt
│ ├── jvmMain
│ └── kotlin
│ │ └── more
│ │ └── math
│ │ ├── native
│ │ └── model
│ │ │ └── NativeProvider.jvm.kt
│ │ └── platform
│ │ └── model
│ │ ├── BigFloat.jvm.kt
│ │ └── BigInt.jvm.kt
│ ├── jvmTest
│ └── kotlin
│ │ └── more
│ │ └── math
│ │ ├── MoreMathTest.kt
│ │ └── platform
│ │ └── model
│ │ └── Factorial_jvmKtTest.kt
│ ├── linuxX64Main
│ └── kotlin
│ │ └── more
│ │ └── math
│ │ ├── native
│ │ └── model
│ │ │ └── NativeProvider.linuxX64.kt
│ │ └── platform
│ │ └── model
│ │ ├── BigFloat.linuxX64.kt
│ │ └── BigInt.linuxX64.kt
│ └── linuxX64Test
│ └── kotlin
│ └── more
│ └── math
│ ├── MoreMathTest.kt
│ └── platform
│ └── model
│ └── Factorial_linuxX64KtTest.kt
└── settings.gradle.kts
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: Deploy to Maven Central
2 |
3 | on:
4 | release:
5 | types: [released, prereleased]
6 |
7 | jobs:
8 | publish:
9 | name: Release build and publish
10 | runs-on: macOS-latest
11 | steps:
12 | - name: Check out code
13 | uses: actions/checkout@v4
14 | - name: Set up JDK 21
15 | uses: actions/setup-java@v4
16 | with:
17 | distribution: 'zulu'
18 | java-version: 21
19 | - name: Make gradlew executable
20 | run: chmod +x ./gradlew
21 | - name: Publish to MavenCentral
22 | run: ./gradlew publishToMavenCentral --no-configuration-cache
23 | env:
24 | ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
25 | ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}
26 | ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.SIGNING_KEY_ID }}
27 | ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_PASSWORD }}
28 | ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.GPG_KEY_CONTENTS }}
--------------------------------------------------------------------------------
/.github/workflows/library unit test.yml:
--------------------------------------------------------------------------------
1 | name: Library unit test
2 |
3 | on:
4 | pull_request:
5 | paths:
6 | - 'library/**'
7 |
8 | jobs:
9 | test:
10 | runs-on: windows-latest
11 | steps:
12 | - uses: actions/checkout@v1
13 | - name: set up JDK
14 | uses: actions/setup-java@v1
15 | with:
16 | java-version: 21
17 | cache: gradle
18 | - name: Make gradlew executable
19 | run: chmod +x ./gradlew
20 | - name: Unit Test
21 | run: ./gradlew :library:JvmTest
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .kotlin/
2 | local.properties
3 | .intellijPlatform/
4 |
5 | # Created by https://www.toptal.com/developers/gitignore/api/swift,xcode,gradle,kotlin,intellij,cocoapods
6 | # Edit at https://www.toptal.com/developers/gitignore?templates=swift,xcode,gradle,kotlin,intellij,cocoapods
7 |
8 | ### CocoaPods ###
9 | ## CocoaPods GitIgnore Template
10 |
11 | # CocoaPods - Only use to conserve bandwidth / Save time on Pushing
12 | # - Also handy if you have a large number of dependant pods
13 | # - AS PER https://guides.cocoapods.org/using/using-cocoapods.html NEVER IGNORE THE LOCK FILE
14 | Pods/
15 |
16 | ### Intellij ###
17 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
18 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
19 |
20 | # Cpp
21 | .cxx
22 |
23 | # User-specific stuff
24 | .idea/**/workspace.xml
25 | .idea/**/tasks.xml
26 | .idea/**/usage.statistics.xml
27 | .idea/**/dictionaries
28 | .idea/**/shelf
29 |
30 | # AWS User-specific
31 | .idea/**/aws.xml
32 |
33 | # Generated files
34 | .idea/**/contentModel.xml
35 |
36 | # Sensitive or high-churn files
37 | .idea/**/dataSources/
38 | .idea/**/dataSources.ids
39 | .idea/**/dataSources.local.xml
40 | .idea/**/sqlDataSources.xml
41 | .idea/**/dynamic.xml
42 | .idea/**/uiDesigner.xml
43 | .idea/**/dbnavigator.xml
44 |
45 | # Gradle
46 | .idea/**/gradle.xml
47 | .idea/**/libraries
48 |
49 | # Gradle and Maven with auto-import
50 | # When using Gradle or Maven with auto-import, you should exclude module files,
51 | # since they will be recreated, and may cause churn. Uncomment if using
52 | # auto-import.
53 | .idea/artifacts
54 | .idea/compiler.xml
55 | .idea/jarRepositories.xml
56 | .idea/modules.xml
57 | .idea/*.iml
58 | .idea/modules
59 | *.iml
60 | *.ipr
61 |
62 | # CMake
63 | cmake-build-*/
64 |
65 | # Mongo Explorer plugin
66 | .idea/**/mongoSettings.xml
67 |
68 | # File-based project format
69 | *.iws
70 |
71 | # IntelliJ
72 | out/
73 |
74 | # mpeltonen/sbt-idea plugin
75 | .idea_modules/
76 |
77 | # JIRA plugin
78 | atlassian-ide-plugin.xml
79 |
80 | # Cursive Clojure plugin
81 | .idea/replstate.xml
82 |
83 | # Crashlytics plugin (for Android Studio and IntelliJ)
84 | com_crashlytics_export_strings.xml
85 | crashlytics.properties
86 | crashlytics-build.properties
87 | fabric.properties
88 |
89 | # Editor-based Rest Client
90 | .idea/httpRequests
91 |
92 | # Android studio 3.1+ serialized cache file
93 | .idea/caches/build_file_checksums.ser
94 |
95 | ### Intellij Patch ###
96 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
97 |
98 | # *.iml
99 | # modules.xml
100 | # .idea/misc.xml
101 | # *.ipr
102 |
103 | # Sonarlint plugin
104 | # https://plugins.jetbrains.com/plugin/7973-sonarlint
105 | .idea/**/sonarlint/
106 |
107 | # SonarQube Plugin
108 | # https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
109 | .idea/**/sonarIssues.xml
110 |
111 | # Markdown Navigator plugin
112 | # https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
113 | .idea/**/markdown-navigator.xml
114 | .idea/**/markdown-navigator-enh.xml
115 | .idea/**/markdown-navigator/
116 |
117 | # Cache file creation bug
118 | # See https://youtrack.jetbrains.com/issue/JBR-2257
119 | .idea/$CACHE_FILE$
120 |
121 | # CodeStream plugin
122 | # https://plugins.jetbrains.com/plugin/12206-codestream
123 | .idea/codestream.xml
124 |
125 | ### Kotlin ###
126 | # Compiled class file
127 | *.class
128 |
129 | # Log file
130 | *.log
131 |
132 | # BlueJ files
133 | *.ctxt
134 |
135 | # Mobile Tools for Java (J2ME)
136 | .mtj.tmp/
137 |
138 | # Package Files #
139 | *.jar
140 | *.war
141 | *.nar
142 | *.ear
143 | *.zip
144 | *.tar.gz
145 | *.rar
146 |
147 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
148 | hs_err_pid*
149 |
150 | ### Swift ###
151 | # Xcode
152 | #
153 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
154 |
155 | ## User settings
156 | xcuserdata/
157 |
158 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
159 | *.xcscmblueprint
160 | *.xccheckout
161 |
162 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
163 | build/
164 | DerivedData/
165 | *.moved-aside
166 | *.pbxuser
167 | !default.pbxuser
168 | *.mode1v3
169 | !default.mode1v3
170 | *.mode2v3
171 | !default.mode2v3
172 | *.perspectivev3
173 | !default.perspectivev3
174 |
175 | ## Obj-C/Swift specific
176 | *.hmap
177 |
178 | ## App packaging
179 | *.ipa
180 | *.dSYM.zip
181 | *.dSYM
182 |
183 | ## Playgrounds
184 | timeline.xctimeline
185 | playground.xcworkspace
186 |
187 | # Swift Package Manager
188 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
189 | # Packages/
190 | # Package.pins
191 | # Package.resolved
192 | # *.xcodeproj
193 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
194 | # hence it is not needed unless you have added a package configuration file to your project
195 | # .swiftpm
196 |
197 | .build/
198 |
199 | # CocoaPods
200 | # We recommend against adding the Pods directory to your .gitignore. However
201 | # you should judge for yourself, the pros and cons are mentioned at:
202 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
203 | # Pods/
204 | # Add this line if you want to avoid checking in source code from the Xcode workspace
205 | # *.xcworkspace
206 |
207 | # Carthage
208 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
209 | # Carthage/Checkouts
210 |
211 | Carthage/Build/
212 |
213 | # Accio dependency management
214 | Dependencies/
215 | .accio/
216 |
217 | # fastlane
218 | # It is recommended to not store the screenshots in the git repo.
219 | # Instead, use fastlane to re-generate the screenshots whenever they are needed.
220 | # For more information about the recommended setup visit:
221 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
222 |
223 | fastlane/report.xml
224 | fastlane/Preview.html
225 | fastlane/screenshots/**/*.png
226 | fastlane/test_output
227 |
228 | # Code Injection
229 | # After new code Injection tools there's a generated folder /iOSInjectionProject
230 | # https://github.com/johnno1962/injectionforxcode
231 |
232 | iOSInjectionProject/
233 |
234 | ### Xcode ###
235 | # Xcode
236 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
237 |
238 |
239 |
240 |
241 | ## Gcc Patch
242 | /*.gcno
243 |
244 | ### Xcode Patch ###
245 | *.xcodeproj/*
246 | !*.xcodeproj/project.pbxproj
247 | !*.xcodeproj/xcshareddata/
248 | !*.xcworkspace/contents.xcworkspacedata
249 | **/xcshareddata/WorkspaceSettings.xcsettings
250 |
251 | ### Gradle ###
252 | .gradle
253 |
254 | # Ignore Gradle GUI config
255 | gradle-app.setting
256 |
257 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
258 | !gradle-wrapper.jar
259 |
260 | # Cache of project
261 | .gradletasknamecache
262 |
263 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
264 | # gradle/wrapper/gradle-wrapper.properties
265 |
266 | ### Gradle Patch ###
267 | **/build/
268 |
269 | # End of https://www.toptal.com/developers/gitignore/api/swift,xcode,gradle,kotlin,intellij,cocoapods
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/kotlinc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright 2023 JetBrains s.r.o. and and respective authors and developers.
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | 
3 | 
4 | 
5 |
6 | 
7 |
8 | ## More math
9 |
10 | Мультиплатформенная библиотека Kotlin, добавляющая математические операции с матрицами, векторами, комбинаторикой и многим другим.
11 |
12 | 
13 |
Эмоджи для телеграм доступны по ссылке https://t.me/addemoji/RkIQSnNfAAA
14 |
15 | ## Подключение
16 |
17 | Чтобы подключить библиотеку нужно добавить строчки ниже в файл ```build.gradle.kts``` вашего мультиплатформенного модуля
18 | ```kotlin
19 | dependencies {
20 | implementation("io.github.plumsoftware:more-math:")
21 | }
22 | ```
23 |
24 | ## Документация на других языках (Documentation)
25 |
26 | + [English](https://github.com/plumsoftware/more-math/blob/develop-v0.0.1/docs/languages/README-en.md)
27 |
28 | ## Содержание
29 |
30 | Эта библиотека предоставляет функциональность для работы с вектором на плоскости, матрицей, комбинаторикой.
31 |
32 | * [Факториал](#Факториал)
33 | * [Тетрация](#Тетрация)
34 | * [Остальное](#Другое)
35 | * [Матрица](#Матрица)
36 | * [Граф](#Граф)
37 | * [Комплексные числа](#Комплексные-числа)
38 | * [Вектор на плоскости](#Вектор)
39 | * [Комбинаторика](#Комбинаторика)
40 |
41 | ## Возможности
42 |
43 | ### Факториал
44 | Вычисление факториала для числа до 21
45 | ```kotlin
46 | val res = MoreMath.factorial(3)
47 | ```
48 |
49 | Вычислить факторил для числа более 20
50 | ```kotlin
51 | val res = MoreMath.bigFactorial(22L)
52 | ```
53 |
54 |
55 |
56 | ### Тетрация
57 | Вычислить тетрацию
58 | ```kotlin
59 | val res = MoreMath.tetraction(2.0, 3)
60 | ```
61 |
62 | Если, число в тетрации большое, то используйте
63 | ```kotlin
64 | val res = MoreMath.bigTetraction(2.0, 40)
65 | ```
66 |
67 |
68 | ### Другое
69 | Чтобы вычислить **наименьшее общее кратное** двух чисел
70 | ```kotlin
71 | val res = MoreMath.gcd(13, 17)
72 | ```
73 |
74 | Вычисление **стандартного отклонения** ряда чисел
75 | ```kotlin
76 | val res = MoreMath.standardDeviation(1.0, 2.0, 3.0)
77 | ```
78 |
79 | **Среднее значение**
80 | ```kotlin
81 | val res = MoreMath.average(1, 2, 3)
82 | ```
83 |
84 | Узнать, положительное или отрицательное число
85 |
86 | ```kotlin
87 | 4.isPositive
88 | (-4).isNegative
89 | ```
90 |
91 |
92 | ### Матрица
93 | Создать матрицу можно тремя способами
94 | ```kotlin
95 | val matrix = matrixOf (
96 | mutableListOf(1, 2),
97 | mutableListOf(3, 4)
98 | )
99 | ```
100 | или
101 | ```kotlin
102 | val matrix = Matrix (
103 | mutableListOf(1, 2),
104 | mutableListOf(3, 4)
105 | )
106 | ```
107 | или
108 | ```kotlin
109 | val matrix = Matrix(size = MatrixSize(row = 3, column = 4))
110 | ```
111 | Последее создаст пустую матрицу. Также можно получить размер матрицы
112 | ```kotlin
113 | val size = matrix.size
114 | ```
115 |
116 | Операторы, доступные для матриц ```+```, ```-```, ```*```, ```pow()```, ```>```, ```>=``` и подобные. Для сравнения контента матриц, используйте метод ```equals()```.
117 | ```kotlin
118 | val matrix1 = matrixOf (
119 | mutableListOf(1, 2),
120 | mutableListOf(3, 4)
121 | )
122 | val matrix2 = matrixOf (
123 | mutableListOf(5, 6),
124 | mutableListOf(7, 8)
125 | )
126 | val matrix3 = matrix1.pow(2)
127 |
128 | val plus = matrix1 + matrix2
129 | val times = matrix1 * matrix2
130 | val minus = matrix1 - matrix2
131 | ```
132 |
133 | Вычислить определитель матрицы
134 | ```kotlin
135 | val det = matrix.determinant()
136 | ```
137 |
138 | Транспонировать матрицу
139 | ```kotlin
140 | val transposedMatrix = matrix.transpose()
141 | ```
142 |
143 | Умножить матрицу на число
144 | ```kotlin
145 | val res = matrix.times(2)
146 | ```
147 |
148 | Найти минимальный или максимальный элемент в матрице.
149 | Если Ваша матрица состоит из ```Double```, ```Long```, ```Float``` или ```Int```, то воспользуйтесь кодом ниже
150 | ```kotlin
151 | val min = matrix.minInMatrix()
152 | val max = matrix.maxInMatrix()
153 | ```
154 | или
155 | ```kotlin
156 | val min = matrix.minInMatrixBy { it }
157 | val max = matrix.maxInMatrixBy { it }
158 | ```
159 |
160 | ### Граф
161 | Создать взвешенный граф
162 | ```kotlin
163 | val graph = Graph(mode = GraphMode.UNDIRECTED)
164 | ```
165 | Где ```VertexType``` - это тип вершины.
166 | ```WeightType``` - это тип веса вершины: ```Int```, ```Double```, ```Long```, ```Float```.
167 | ```mode``` - это тип графа: ```UNDIRECTED```, ```DIRECTED```.
168 |
169 | Для создания связи нужно добавить вершины:
170 | ```kotlin
171 | val graph = Graph()
172 |
173 | val vertexA = Vertex(id = "A")
174 | val vertexB = Vertex(id = "B")
175 | val vertexC = Vertex(id = "C")
176 | val vertexD = Vertex(id = "D")
177 |
178 | graph.addVertex(vertexA)
179 | graph.addVertex(vertexB)
180 | graph.addVertex(vertexC)
181 | graph.addVertex(vertexD)
182 | ```
183 |
184 | Затем создайте связь между вершинами
185 | ```kotlin
186 | graph.createConnection(from = vertexA, to = vertexB, weight = 2)
187 | ```
188 |
189 | Получить минимальный путь в графе от и до вершины
190 | ```kotlin
191 | val minPath: GraphPath = graph.minPath(from = Vertex("A"), to = Vertex("B"))
192 | ```
193 | В результате будет возвращен ```GraphPath```, который содержит пары - вершины и суммарный путь до следующей вершины.
194 |
195 | Получить все вершины
196 | ```kotlin
197 | val vertices = graph.vertices
198 | ```
199 |
200 | Получить все связи
201 | ```kotlin
202 | val vertices = graph.connections
203 | ```
204 |
205 | Узнать, есть ли вершина
206 | ```kotlin
207 | val vertex: Vertex? = graph[someVertex]
208 | ```
209 | Это вернёт ```null```, если вершины в графе нет.
210 |
211 | Заменить вершину в графе
212 | ```kotlin
213 | val newVertex = Vertex("A")
214 | val oldVertex = Vertex("B") //Эта вершина уже есть в графе
215 | graph.set(oldVertex, newVertex, SetVertexMode.NEW_FROM_TO)
216 | ```
217 | Это заменит все вершины во всех связях в графе и удалит старую вершину.
218 | Если вы хотите заменить только начальные вершины в связях или конечные, то используйте ```NEW_FROM``` или ```NEW_TO``` соответственно.
219 |
220 | Для удаления всех связей используйте:
221 | ```kotlin
222 | graph.removeConnectionsByVertex(someVertex, RemoveVertexMode.TO)
223 | ```
224 | Это удалит все связи, где есть переданная конечная вершина.
225 | Если нужно удалить только начальные вершины или обе (начальную и конечную) из связей, то используйте ```FROM``` или ```BOTH``` соответственно.
226 |
227 | Для получения всех вершин без связей или наоборот всех вершин в связях
228 | ```kotlin
229 | val freeList = graph.getFreeVertices()
230 | val busyList = graph.getBusyVertices()
231 | ```
232 |
233 |
234 | ### Комплексные числа
235 | Создать комплексное число
236 | ```kotlin
237 | val complex: Complex = complex(-4.0)
238 | ```
239 | В результате будет ```0.0 - 2.0i```
240 |
241 | Если Вам нужно указать реальную часть числа, то воспользуйтесь
242 | ```kotlin
243 | val complex: Complex = complex(3, -4.0)
244 | ```
245 | В результате будет ```3.0 - 2.0i```
246 |
247 | Получить алгебраическую или геометрическую форму можно таким образом
248 | ```kotlin
249 | val algebraic = complex.toAlgebraic()
250 | val geometric = complex.toGeometric()
251 | ```
252 |
253 | С комплексными числами можно выполнять ```+```, ```-```, ```*```, ```/```. Также доступны ```equals()``` и ```hashCode()```.
254 |
255 |
256 |
257 | ### Вектор
258 |
259 | #### Вектор на плоскости
260 | Создание вектора аналогично созданию матрицы
261 | ```kotlin
262 | val vector2 = vector2Of(1 , 2)
263 | ```
264 | или
265 | ```kotlin
266 | val vector2 = Vector2(1 , 2)
267 | ```
268 |
269 | С векторами на плоскости доступны следующие операторы ```+```, ```-```, ```*```, ```/```. Также Вы можете использовать ```equals()``` и ```length()```.
270 | ```kotlin
271 | val vector1 = vector2Of(1, 2)
272 | val vector2 = vector2Of(3, 4)
273 |
274 | val plus = vector1 + vector2
275 | val minus = vector1 - vector2
276 | val times = vector1 * vector2
277 | val div = vector1 / vector2
278 | val length = vector1.length()
279 | ```
280 |
281 |
282 |
283 | ### Комбинаторика
284 |
285 | Комбинации из 5 элементов по 2 элемента
286 | ```kotlin
287 | val res = MoreMath.combinations(5, 2)
288 | ```
289 |
290 | Размещения
291 | ```kotlin
292 | val res = MoreMath.placements(5, 2)
293 | ```
294 |
295 | Биноменальный коэффициент
296 | ```kotlin
297 | val res = MoreMath.binomialCoefficient(5, 2)
298 | ```
299 |
--------------------------------------------------------------------------------
/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | alias(libs.plugins.androidLibrary).apply(false)
3 | alias(libs.plugins.kotlinMultiplatform).apply(false)
4 | alias(libs.plugins.vanniktech.mavenPublish).apply(false)
5 | alias(libs.plugins.kotlin.android) apply false
6 | }
7 |
--------------------------------------------------------------------------------
/docs/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/plumsoftware/more-math/9d8566fddb49dba72f069f6335654d93b8fb5b63/docs/images/logo.png
--------------------------------------------------------------------------------
/docs/images/telegram.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/languages/README-en.md:
--------------------------------------------------------------------------------
1 | 
2 | 
3 | 
4 | 
5 |
6 | 
7 |
8 | # More math
9 |
10 | Kotlin multiplatform library adding mathematical operations with matrices, vectors, combinatorics and much more.
11 |  Telegram emoji are available below the link https://t.me/addemoji/RkIQSnNfAAA
12 |
13 | 
14 |
Telegram emoji are available below the link https://t.me/addemoji/RkIQSnNfAAA
15 |
16 | ## Add
17 |
18 | To connect the library, you need to add the lines below to the ```build.gradle.kts``` file of your multiplatform module
19 | ```kotlin
20 | dependencies {
21 | implementation("io.github.plumsoftware:more-math:")
22 | }
23 | ```
24 |
25 | # Overview
26 |
27 | This library provides functionality to work with Vector on a plane, Matrix, Combinatorics.
28 |
29 | * [Factorial](#Factorial)
30 | * [Tetraction](#Tetraction)
31 | * [Other](#Other)
32 | * [Matrix](#Matrix)
33 | * [Graph](#Graph)
34 | * [Complex numbers](#Complex-numbers)
35 | * [Vector on plane](#Vector)
36 | * [Combinatorics](#Combinatorics)
37 |
38 | ## Usage
39 |
40 | ### Factorial
41 | Use factorial for input below 21 like this
42 | ```kotlin
43 | val res = MoreMath.factorial(3)
44 | ```
45 |
46 | Use factorial for input more 20 like this
47 | ```kotlin
48 | val res = MoreMath.bigFactorial(22L)
49 | ```
50 |
51 |
52 | ### Tetraction
53 | To get tetraction use this
54 | ```kotlin
55 | val res = MoreMath.tetraction(2.0, 3)
56 | ```
57 |
58 | To work with big numbers
59 | ```kotlin
60 | val res = MoreMath.bigTetraction(2.0, 40)
61 | ```
62 |
63 |
64 | ### Other
65 | To get **least common multiple**
66 | ```kotlin
67 | val res = MoreMath.gcd(13, 17)
68 | ```
69 |
70 | Get a **standart deviation**
71 | ```kotlin
72 | val res = MoreMath.standardDeviation(1.0, 2.0, 3.0)
73 | ```
74 |
75 | Get a **average**
76 | ```kotlin
77 | val res = MoreMath.average(1, 2, 3)
78 | ```
79 |
80 | Positive or negative number
81 |
82 | ```kotlin
83 | 4.isPositive
84 | (-4).isNegative
85 | ```
86 |
87 |
88 | ### Matrix
89 | To create matrix just write
90 | ```kotlin
91 | val matrix = matrixOf (
92 | mutableListOf(1, 2),
93 | mutableListOf(3, 4)
94 | )
95 | ```
96 | or
97 | ```kotlin
98 | val matrix = Matrix (
99 | mutableListOf(1, 2),
100 | mutableListOf(3, 4)
101 | )
102 | ```
103 | or with matrix size
104 | ```kotlin
105 | val matrix = Matrix(size = MatrixSize(row = 3, column = 4))
106 | ```
107 | It creates an empty matrix. Get a matrix size like this
108 | ```kotlin
109 | val size = matrix.size
110 | ```
111 |
112 | You can ```+```, ```-```, ```*```, ```pow()```, ```>```, ```!=``` etc. To compare a matrix content use ```equals()```.
113 | ```kotlin
114 | val matrix1 = matrixOf (
115 | mutableListOf(1, 2),
116 | mutableListOf(3, 4)
117 | )
118 | val matrix2 = matrixOf (
119 | mutableListOf(5, 6),
120 | mutableListOf(7, 8)
121 | )
122 | val matrix3 = matrix1.pow(2)
123 |
124 | val plus = matrix1 + matrix2
125 | val times = matrix1 * matrix2
126 | val minus = matrix1 - matrix2
127 | ```
128 |
129 | Get a determinant
130 | ```kotlin
131 | val det = matrix.determinant()
132 | ```
133 |
134 | Transpose matrix
135 | ```kotlin
136 | val transposedMatrix = matrix.transpose()
137 | ```
138 |
139 | Times matrix with number
140 | ```kotlin
141 | val res = matrix.times(2)
142 | ```
143 |
144 | To find min or max item in matrix.
145 | If your matrix contains one of ```Double```, ```Long```, ```Float```, ```Int```, use the code below
146 | ```kotlin
147 | val min = matrix.minInMatrix()
148 | val max = matrix.maxInMatrix()
149 | ```
150 | or
151 | ```kotlin
152 | val min = matrix.minInMatrixBy { it }
153 | val max = matrix.maxInMatrixBy { it }
154 | ```
155 |
156 | ### Graph
157 | Create a weighted graph
158 | ```kotlin
159 | val graph = Graph(mode = GraphMode.UNDIRECTED)
160 | ```
161 |
162 | Where VertexType is the type of the vertex. WeightType is the type of the vertex weight: Int, Double, Long, Float. mode is the type of the graph: UNDIRECTED, DIRECTED.
163 |
164 | To create a connection, you need to add vertices:
165 | ```kotlin
166 | val graph = Graph()
167 |
168 | val vertexA = Vertex(id = "A")
169 | val vertexB = Vertex(id = "B")
170 | val vertexC = Vertex(id = "C")
171 | val vertexD = Vertex(id = "D")
172 |
173 | graph.addVertex(vertexA)
174 | graph.addVertex(vertexB)
175 | graph.addVertex(vertexC)
176 | graph.addVertex(vertexD)
177 | ```
178 |
179 | Then create a connection between the vertices
180 | ```kotlin
181 | graph.createConnection(from = vertexA, to = vertexB, weight = 2)
182 | ```
183 |
184 | Get a min path in graph:
185 | ```kotlin
186 | val minPath: GraphPath = graph.minPath(from = Vertex("A"), to = Vertex("B"))
187 | ```
188 | It returns a ```GraphPath``` which contains a list of pairs - vertex and sum weight to next vertex.
189 |
190 | Get all vertices
191 | ```kotlin
192 | val vertices = graph.vertices
193 | ```
194 |
195 | Get all connections
196 | ```kotlin
197 | val vertices = graph.connections
198 | ```
199 | Check if a vertex exists
200 | ```kotlin
201 | val vertex: Vertex? = graph[someVertex]
202 | ```
203 | This will return null if the vertex does not exist in the graph.
204 |
205 | Replace a vertex in a graph
206 |
207 | ```kotlin
208 | val newVertex = Vertex("A")
209 | val oldVertex = Vertex("B") //This vertex is already in the graph
210 | graph.set(oldVertex, newVertex, SetVertexMode.NEW_FROM_TO)
211 | ```
212 | This will replace all nodes in all links in the graph and remove the old node. If you want to replace only the start nodes in links or the end nodes, use NEW_FROM or NEW_TO respectively.
213 |
214 | To remove all connections use:
215 | ```kotlin
216 | graph.removeConnectionsByVertex(someVertex, RemoveVertexMode.TO)
217 | ```
218 |
219 | This will remove all links where the given end node is present. If you want to remove only the start nodes or both (start and end) from links, use FROM or BOTH respectively.
220 |
221 | To get all nodes without links or vice versa all nodes in links
222 | ```kotlin
223 | val freeList = graph.getFreeVertices()
224 | val busyList = graph.getBusyVertices()
225 | ```
226 |
227 |
228 | ### Complex numbers
229 | Create a complex number
230 | ```kotlin
231 | val complex: Complex = complex(-4.0)
232 | ```
233 | This will be ```0.0 - 2.0i```
234 |
235 | If you need to specify the real part of the number, use
236 | ```kotlin
237 | val complex: Complex = MoreMath.complex(3, -4.0)
238 | ```
239 | This will be ```3.0 - 2.0i```
240 |
241 | T0 find algebraic or geometric form
242 | ```kotlin
243 | val algebraic = complex.toAlgebraic()
244 | val geometric = complex.toGeometric()
245 | ```
246 |
247 | With complex numbers, you can perform ```+```, ```-```, ```*```, ```/```. ```equals()``` and ```hashCode()``` are also available.
248 |
249 |
250 |
251 | ### Vector
252 |
253 | #### On plane
254 | To create vector
255 | ```kotlin
256 | val vector2 = vector2Of(1 , 2)
257 | ```
258 | or
259 | ```kotlin
260 | val vector2 = Vector2(1 , 2)
261 | ```
262 |
263 | You can ```+```, ```-```, ```*```, ```/``` vector2. Also ```equals()``` and ```length()``` are available.
264 | ```kotlin
265 | val vector1 = vector2Of(1, 2)
266 | val vector2 = vector2Of(3, 4)
267 |
268 | val plus = vector1 + vector2
269 | val minus = vector1 - vector2
270 | val times = vector1 * vector2
271 | val div = vector1 / vector2
272 | val length = vector1.length()
273 | ```
274 |
275 |
276 |
277 | ### Combinatorics
278 |
279 | Combinations of 5 elements by 2 elements
280 | ```kotlin
281 | val res = MoreMath.combinations(5, 2)
282 | ```
283 |
284 | Placements
285 | ```kotlin
286 | val res = MoreMath.placements(5, 2)
287 | ```
288 |
289 | Binomial coefficient
290 | ```kotlin
291 | val res = MoreMath.binomialCoefficient(5, 2)
292 | ```
293 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | #Gradle
2 | org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx2048M"
3 | org.gradle.caching=true
4 | org.gradle.configuration-cache=true
5 | #Kotlin
6 | kotlin.code.style=official
7 | kotlin.js.compiler=ir
8 | #MPP
9 | kotlin.mpp.enableCInteropCommonization=true
10 | #Android
11 | android.useAndroidX=true
12 | android.nonTransitiveRClass=true
13 | #KMP
14 | kotlin.native.ignoreDisabledTargets=true
15 |
--------------------------------------------------------------------------------
/gradle/libs.versions.toml:
--------------------------------------------------------------------------------
1 | [versions]
2 | agp = "8.3.0"
3 | kotlin = "2.0.0"
4 | nexus-publish = "2.0.0"
5 | android-minSdk = "21"
6 | android-compileSdk = "35"
7 | mavenPublish = "0.29.0"
8 |
9 | #Coroutines
10 | kotlin-coroutines = "1.9.0"
11 | kotlinVersion = "1.9.0"
12 | coreKtx = "1.15.0"
13 | junit = "4.13.2"
14 | junitVersion = "1.2.1"
15 | espressoCore = "3.6.1"
16 | appcompat = "1.7.0"
17 | material = "1.12.0"
18 |
19 | [libraries]
20 | kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
21 |
22 | #Coroutines
23 | kotlin-coroutines = {module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlin-coroutines"}
24 | kotlin-coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "kotlin-coroutines" }
25 | core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
26 | junit = { group = "junit", name = "junit", version.ref = "junit" }
27 | ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
28 | espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
29 | appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
30 | material = { group = "com.google.android.material", name = "material", version.ref = "material" }
31 |
32 | [plugins]
33 | androidLibrary = { id = "com.android.library", version.ref = "agp" }
34 | kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
35 | vanniktech-mavenPublish = {id = "com.vanniktech.maven.publish", version.ref = "mavenPublish"}
36 | kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlinVersion" }
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/plumsoftware/more-math/9d8566fddb49dba72f069f6335654d93b8fb5b63/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
4 | networkTimeout=10000
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | #
21 | # Gradle start up script for POSIX generated by Gradle.
22 | #
23 | # Important for running:
24 | #
25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26 | # noncompliant, but you have some other compliant shell such as ksh or
27 | # bash, then to run this script, type that shell name before the whole
28 | # command line, like:
29 | #
30 | # ksh Gradle
31 | #
32 | # Busybox and similar reduced shells will NOT work, because this script
33 | # requires all of these POSIX shell features:
34 | # * functions;
35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37 | # * compound commands having a testable exit status, especially «case»;
38 | # * various built-in commands including «command», «set», and «ulimit».
39 | #
40 | # Important for patching:
41 | #
42 | # (2) This script targets any POSIX shell, so it avoids extensions provided
43 | # by Bash, Ksh, etc; in particular arrays are avoided.
44 | #
45 | # The "traditional" practice of packing multiple parameters into a
46 | # space-separated string is a well documented source of bugs and security
47 | # problems, so this is (mostly) avoided, by progressively accumulating
48 | # options in "$@", and eventually passing that to Java.
49 | #
50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52 | # see the in-line comments for details.
53 | #
54 | # There are tweaks for specific operating systems such as AIX, CygWin,
55 | # Darwin, MinGW, and NonStop.
56 | #
57 | # (3) This script is generated from the Groovy template
58 | # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59 | # within the Gradle project.
60 | #
61 | # You can find Gradle at https://github.com/gradle/gradle/.
62 | #
63 | ##############################################################################
64 |
65 | # Attempt to set APP_HOME
66 |
67 | # Resolve links: $0 may be a link
68 | app_path=$0
69 |
70 | # Need this for daisy-chained symlinks.
71 | while
72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
73 | [ -h "$app_path" ]
74 | do
75 | ls=$( ls -ld "$app_path" )
76 | link=${ls#*' -> '}
77 | case $link in #(
78 | /*) app_path=$link ;; #(
79 | *) app_path=$APP_HOME$link ;;
80 | esac
81 | done
82 |
83 | # This is normally unused
84 | # shellcheck disable=SC2034
85 | APP_BASE_NAME=${0##*/}
86 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
87 |
88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137 |
138 | Please set the JAVA_HOME variable in your environment to match the
139 | location of your Java installation."
140 | fi
141 |
142 | # Increase the maximum file descriptors if we can.
143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144 | case $MAX_FD in #(
145 | max*)
146 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
147 | # shellcheck disable=SC3045
148 | MAX_FD=$( ulimit -H -n ) ||
149 | warn "Could not query maximum file descriptor limit"
150 | esac
151 | case $MAX_FD in #(
152 | '' | soft) :;; #(
153 | *)
154 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
155 | # shellcheck disable=SC3045
156 | ulimit -n "$MAX_FD" ||
157 | warn "Could not set maximum file descriptor limit to $MAX_FD"
158 | esac
159 | fi
160 |
161 | # Collect all arguments for the java command, stacking in reverse order:
162 | # * args from the command line
163 | # * the main class name
164 | # * -classpath
165 | # * -D...appname settings
166 | # * --module-path (only if needed)
167 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
168 |
169 | # For Cygwin or MSYS, switch paths to Windows format before running java
170 | if "$cygwin" || "$msys" ; then
171 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
172 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
173 |
174 | JAVACMD=$( cygpath --unix "$JAVACMD" )
175 |
176 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
177 | for arg do
178 | if
179 | case $arg in #(
180 | -*) false ;; # don't mess with options #(
181 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
182 | [ -e "$t" ] ;; #(
183 | *) false ;;
184 | esac
185 | then
186 | arg=$( cygpath --path --ignore --mixed "$arg" )
187 | fi
188 | # Roll the args list around exactly as many times as the number of
189 | # args, so each arg winds up back in the position where it started, but
190 | # possibly modified.
191 | #
192 | # NB: a `for` loop captures its iteration list before it begins, so
193 | # changing the positional parameters here affects neither the number of
194 | # iterations, nor the values presented in `arg`.
195 | shift # remove old arg
196 | set -- "$@" "$arg" # push replacement arg
197 | done
198 | fi
199 |
200 | # Collect all arguments for the java command;
201 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
202 | # shell script including quotes and variable substitutions, so put them in
203 | # double quotes to make sure that they get re-expanded; and
204 | # * put everything else in single quotes, so that it's not re-expanded.
205 |
206 | set -- \
207 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
208 | -classpath "$CLASSPATH" \
209 | org.gradle.wrapper.GradleWrapperMain \
210 | "$@"
211 |
212 | # Stop when "xargs" is not available.
213 | if ! command -v xargs >/dev/null 2>&1
214 | then
215 | die "xargs is not available"
216 | fi
217 |
218 | # Use "xargs" to parse quoted args.
219 | #
220 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
221 | #
222 | # In Bash we could simply go:
223 | #
224 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
225 | # set -- "${ARGS[@]}" "$@"
226 | #
227 | # but POSIX shell has neither arrays nor command substitution, so instead we
228 | # post-process each arg (as a line of input to sed) to backslash-escape any
229 | # character that might be a shell metacharacter, then use eval to reverse
230 | # that process (while maintaining the separation between arguments), and wrap
231 | # the whole thing up as a single "set" statement.
232 | #
233 | # This will of course break if any of these variables contains a newline or
234 | # an unmatched quote.
235 | #
236 |
237 | eval "set -- $(
238 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
239 | xargs -n1 |
240 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
241 | tr '\n' ' '
242 | )" '"$@"'
243 |
244 | exec "$JAVACMD" "$@"
245 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%"=="" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%"=="" set DIRNAME=.
29 | @rem This is normally unused
30 | set APP_BASE_NAME=%~n0
31 | set APP_HOME=%DIRNAME%
32 |
33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
35 |
36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
38 |
39 | @rem Find java.exe
40 | if defined JAVA_HOME goto findJavaFromJavaHome
41 |
42 | set JAVA_EXE=java.exe
43 | %JAVA_EXE% -version >NUL 2>&1
44 | if %ERRORLEVEL% equ 0 goto execute
45 |
46 | echo.
47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
48 | echo.
49 | echo Please set the JAVA_HOME variable in your environment to match the
50 | echo location of your Java installation.
51 |
52 | goto fail
53 |
54 | :findJavaFromJavaHome
55 | set JAVA_HOME=%JAVA_HOME:"=%
56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
57 |
58 | if exist "%JAVA_EXE%" goto execute
59 |
60 | echo.
61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
62 | echo.
63 | echo Please set the JAVA_HOME variable in your environment to match the
64 | echo location of your Java installation.
65 |
66 | goto fail
67 |
68 | :execute
69 | @rem Setup the command line
70 |
71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
72 |
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if %ERRORLEVEL% equ 0 goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | set EXIT_CODE=%ERRORLEVEL%
85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
87 | exit /b %EXIT_CODE%
88 |
89 | :mainEnd
90 | if "%OS%"=="Windows_NT" endlocal
91 |
92 | :omega
93 |
--------------------------------------------------------------------------------
/library/build.gradle.kts:
--------------------------------------------------------------------------------
1 | import com.vanniktech.maven.publish.SonatypeHost
2 | import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
3 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget
4 |
5 | plugins {
6 | alias(libs.plugins.kotlinMultiplatform)
7 | alias(libs.plugins.androidLibrary)
8 | alias(libs.plugins.vanniktech.mavenPublish)
9 | }
10 |
11 | kotlin {
12 | jvm {
13 | compilations.all {
14 | kotlinOptions.jvmTarget = "1.8"
15 | }
16 | testRuns["test"].executionTask.configure {
17 | useJUnitPlatform()
18 | }
19 | }
20 |
21 | androidTarget {
22 | publishLibraryVariants("release")
23 | @OptIn(ExperimentalKotlinGradlePluginApi::class)
24 | compilerOptions {
25 | jvmTarget.set(JvmTarget.JVM_1_8)
26 | }
27 | }
28 |
29 | iosX64()
30 | iosArm64()
31 | iosSimulatorArm64()
32 |
33 | linuxX64()
34 |
35 | applyDefaultHierarchyTemplate()
36 |
37 | sourceSets {
38 | val commonMain by getting {
39 | dependencies {}
40 | }
41 | val commonTest by getting {
42 | dependencies {
43 | implementation(libs.kotlin.test)
44 | }
45 | }
46 | }
47 | }
48 |
49 | android {
50 | namespace = "more.math"
51 | compileSdk = libs.versions.android.compileSdk.get().toInt()
52 | defaultConfig {
53 | minSdk = libs.versions.android.minSdk.get().toInt()
54 |
55 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
56 | }
57 |
58 | externalNativeBuild {
59 | cmake {
60 | path("src/commonMain/cpp/CMakeLists.txt")
61 | version = "3.22.1"
62 | }
63 | }
64 |
65 | dependencies {
66 | testImplementation(libs.junit)
67 | androidTestImplementation(libs.ext.junit)
68 | androidTestImplementation(libs.espresso.core)
69 | }
70 | }
71 |
72 | mavenPublishing {
73 |
74 | group = "io.github.plumsoftware"
75 | version = "1.1.1"
76 |
77 | publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL)
78 |
79 | signAllPublications()
80 |
81 | coordinates(group.toString(), "more-math", version.toString())
82 |
83 | pom {
84 | name.set("More math")
85 | description.set("Это KMP библиотека для работы с математикой.")
86 | url.set("https://github.com/plumsoftware/more-math")
87 |
88 | licenses {
89 | license {
90 | name.set("MIT")
91 | url.set("https://opensource.org/licenses/MIT")
92 | }
93 | }
94 | developers {
95 | developer {
96 | id.set("https://t.me/Sl1vka")
97 | name.set("Vyacheslav Deych")
98 | organization.set("Plumsoftware")
99 | organizationUrl.set("https://github.com/plumsoftware")
100 | }
101 | }
102 | scm {
103 | url.set("https://github.com/plumsoftware/more-math")
104 | connection.set("scm:git:git://github.com/plumsoftware/more-math")
105 | developerConnection = "scm:git:ssh://git@github.com:plumsoftware/more-math.git"
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/library/src/androidMain/kotlin/more/math/native/model/NativeProvider.android.kt:
--------------------------------------------------------------------------------
1 | package more.math.native.model
2 |
3 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
4 | internal actual class NativeProvider actual constructor() {
5 |
6 | companion object {
7 | init {
8 | System.loadLibrary("nativelib")
9 | }
10 | }
11 |
12 | private external fun cppFactorial(number: Int) : Long
13 |
14 | private external fun cppLongFactorial(number: Long) : Long
15 |
16 | private external fun cppAverage(vararg number: Int) : Double
17 |
18 | private external fun cppStandardDeviation(vararg numbers: Double) : Double
19 |
20 | private external fun cppTetraction(number: Double, other: Int) : Double
21 |
22 | private external fun cppGcd(a: Int, b: Int) : Int
23 |
24 | actual fun nativeFactorial(number: Int): Long {
25 | return cppFactorial(number = number)
26 | }
27 |
28 | actual fun nativeFactorial(number: Long): Long {
29 | return cppLongFactorial(number = number)
30 | }
31 |
32 | actual fun nativeAverage(vararg numbers: Int) : Double {
33 | return cppAverage(*numbers)
34 | }
35 |
36 | actual fun standardDeviation(vararg numbers: Double) : Double {
37 | return cppStandardDeviation(*numbers)
38 | }
39 |
40 | actual fun tetraction(number: Double, other: Int) : Double {
41 | return cppTetraction(number = number, other = other)
42 | }
43 |
44 | actual fun gcd(a: Int, b: Int): Int {
45 | return cppGcd(a, b)
46 | }
47 | }
--------------------------------------------------------------------------------
/library/src/androidMain/kotlin/more/math/platform/model/BigFloat.android.kt:
--------------------------------------------------------------------------------
1 | package more.math.platform.model
2 |
3 | import java.math.BigDecimal
4 |
5 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
6 | actual class BigFloat actual constructor(value: String) {
7 | actual companion object {
8 | actual val ZERO: BigFloat get() = BigFloat(BigDecimal.ZERO.toString())
9 | actual val ONE: BigFloat get() = BigFloat(BigDecimal.ONE.toString())
10 | }
11 |
12 | private val bigFloat = BigDecimal(value)
13 |
14 | actual fun add(other: BigFloat): BigFloat {
15 | return BigFloat(this.bigFloat.add(other.bigFloat).toString())
16 | }
17 |
18 | actual fun multiply(other: BigFloat): BigFloat {
19 | return BigFloat(this.bigFloat.multiply(other.bigFloat).toString())
20 | }
21 |
22 | actual override fun toString(): String {
23 | return this.bigFloat.toString()
24 | }
25 | }
--------------------------------------------------------------------------------
/library/src/androidMain/kotlin/more/math/platform/model/BigInt.android.kt:
--------------------------------------------------------------------------------
1 | package more.math.platform.model
2 |
3 | import java.math.BigInteger
4 |
5 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
6 | actual class BigInt actual constructor(value: String) {
7 |
8 | actual companion object {
9 | actual val ZERO: BigInt
10 | get() = BigInt("0")
11 | actual val ONE: BigInt
12 | get() = BigInt("1")
13 | }
14 |
15 | private val bigInt = BigInteger(value)
16 |
17 | actual fun add(other: BigInt): BigInt {
18 | return BigInt(this.bigInt.add(other.bigInt).toString())
19 | }
20 |
21 | actual fun multiply(other: BigInt): BigInt {
22 | return BigInt(this.bigInt.multiply(other.bigInt).toString())
23 | }
24 |
25 | actual override fun toString(): String {
26 | return this.bigInt.toString()
27 | }
28 | }
--------------------------------------------------------------------------------
/library/src/androidTest/java/more/math/native/model/NativeLibTest.kt:
--------------------------------------------------------------------------------
1 | package more.math.native.model
2 |
3 | import androidx.test.ext.junit.runners.AndroidJUnit4
4 | import more.math.MoreMath
5 | import org.junit.Test
6 | import org.junit.runner.RunWith
7 | import org.junit.Assert.*
8 |
9 | @RunWith(AndroidJUnit4::class)
10 | class NativeLibTest {
11 |
12 | @Test
13 | fun nativeFactorial() {
14 | val actual = MoreMath.factorial(n = 3)
15 | val expected = 6L
16 | assertEquals(expected, actual)
17 |
18 | val actual1 = MoreMath.factorial(n = 3L)
19 | val expected1 = 6L
20 | assertEquals(expected1, actual1)
21 | }
22 |
23 | @Test
24 | fun average() {
25 | val exp: Double = 2.0
26 | val act: Double = MoreMath.average(1, 2, 3)
27 | assertEquals(exp.toString(), act.toString())
28 | }
29 |
30 | @Test
31 | fun tetraction() {
32 | val result = MoreMath.tetraction(number = 2.0, other = 3)
33 | assertEquals(16.0.toString(), result.toString())
34 | }
35 |
36 | @Test
37 | fun stdDev() {
38 | val exp: Double = 1.0
39 | val act: Double = MoreMath.standardDeviation(1.0, 2.0, 3.0)
40 | assertEquals(exp.toString(), act.toString())
41 | }
42 |
43 | @Test
44 | fun gcd() {
45 | val exp: Int = 5
46 | val act: Int = MoreMath.gcd(10, 15)
47 | assertEquals(exp, act)
48 | }
49 | }
--------------------------------------------------------------------------------
/library/src/androidUnitTest/kotlin/more.math/MoreMathTest.kt:
--------------------------------------------------------------------------------
1 | package more.math
2 |
3 | import more.math.matrix.model.Matrix
4 | import more.math.matrix.model.determinant
5 | import more.math.matrix.model.transpose
6 | import more.math.vector.model.Vector2
7 | import kotlin.test.Test
8 | import kotlin.test.assertEquals
9 |
10 | class MoreMathTest {
11 |
12 | @Test
13 | fun test() {
14 | val matrix = matrixOf(
15 | mutableListOf(1,2),
16 | mutableListOf(3,4),
17 | )
18 | val vector1 = vector2Of(1, 2)
19 | val vector2 = vector2Of(3, 4)
20 |
21 | assertEquals(expected = -2.0, actual = matrix.determinant())
22 | assertEquals(expected = 6, MoreMath.factorial(3))
23 | assertEquals(expected = 2.0, MoreMath.average(1, 2, 3))
24 | assertEquals(expected = Matrix(mutableListOf(1, 3), mutableListOf(2, 4)), matrix.transpose())
25 | assertEquals(expected = 16.0, MoreMath.tetraction(2.0, 3))
26 | assertEquals(expected = Vector2(x = 4, y = 6), actual = (vector1 + vector2))
27 | }
28 | }
--------------------------------------------------------------------------------
/library/src/androidUnitTest/kotlin/more/math/platform/model/Factorial_androidKtTest.kt:
--------------------------------------------------------------------------------
1 | package more.math.platform.model
2 |
3 | import more.math.MoreMath
4 |
5 | import org.junit.Test
6 | import java.math.BigInteger
7 |
8 | class Factorial_androidKtTest {
9 |
10 | @Test
11 | fun bigFactorial() {
12 | val n = 22L
13 | val result = MoreMath.bigFactorial(n)
14 | kotlin.test.assertEquals(
15 | expected = BigInteger("1124000727777607680000").toString(),
16 | actual = result.toString()
17 | )
18 | }
19 | }
--------------------------------------------------------------------------------
/library/src/commonMain/cpp/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # For more information about using CMake with Android Studio, read the
2 | # documentation: https://d.android.com/studio/projects/add-native-code.html.
3 | # For more examples on how to use CMake, see https://github.com/android/ndk-samples.
4 |
5 | # Sets the minimum CMake version required for this project.
6 | cmake_minimum_required(VERSION 3.22.1)
7 |
8 | # Declares the project name. The project name can be accessed via ${ PROJECT_NAME},
9 | # Since this is the top level CMakeLists.txt, the project name is also accessible
10 | # with ${CMAKE_PROJECT_NAME} (both CMake variables are in-sync within the top level
11 | # build script scope).
12 | project("nativelib")
13 |
14 | # Creates and names a library, sets it as either STATIC
15 | # or SHARED, and provides the relative paths to its source code.
16 | # You can define multiple libraries, and CMake builds them for you.
17 | # Gradle automatically packages shared libraries with your APK.
18 | #
19 | # In this top level CMakeLists.txt, ${CMAKE_PROJECT_NAME} is used to define
20 | # the target library name; in the sub-module's CMakeLists.txt, ${PROJECT_NAME}
21 | # is preferred for the same purpose.
22 | #
23 | # In order to load a library into your app from Java/Kotlin, you must call
24 | # System.loadLibrary() and pass the name of the library defined here;
25 | # for GameActivity/NativeActivity derived applications, the same library name must be
26 | # used in the AndroidManifest.xml file.
27 | add_library(${CMAKE_PROJECT_NAME} SHARED
28 | # List C/C++ source files with relative paths to this CMakeLists.txt.
29 | hyperoperator.cpp
30 | nativelib.cpp)
31 |
32 | # Specifies libraries CMake should link to your target library. You
33 | # can link libraries from various origins, such as libraries defined in this
34 | # build script, prebuilt third-party libraries, or Android system libraries.
35 | target_link_libraries(${CMAKE_PROJECT_NAME}
36 | # List libraries link to the target library
37 | android
38 | log)
--------------------------------------------------------------------------------
/library/src/commonMain/cpp/hyperoperator.cpp:
--------------------------------------------------------------------------------
1 | #include "hyperoperator.h"
2 | #include
3 |
4 | double tetraction(double number, int other) {
5 | if (other == 0) {
6 | return 1.0;
7 | } else {
8 | return pow(number, tetraction(number, other - 1));
9 | }
10 | }
11 |
12 | unsigned long factorial(int number) {
13 | unsigned long long result = 1;
14 |
15 | for (int i = 2; i <= number; ++i) {
16 | result *= i;
17 |
18 | if (result > 9223372036854775807ULL) {
19 | return -1;
20 | }
21 | }
22 |
23 | return result;
24 | }
25 |
26 | unsigned long factorial_(long number) {
27 | unsigned long long result = 1;
28 |
29 | for (int i = 2; i <= number; ++i) {
30 | result *= i;
31 |
32 | if (result > 9223372036854775807ULL) {
33 | return -1;
34 | }
35 | }
36 |
37 | return result;
38 | }
39 |
40 | double average(const int* numbers, size_t length) {
41 | if (length == 0) {
42 | return 0.0;
43 | }
44 |
45 | int sum = 0;
46 | for (size_t i = 0; i < length; i++) {
47 | sum += numbers[i];
48 | }
49 | return static_cast(sum) / length;
50 | }
51 |
52 | double standardDeviation(const double* numbers, size_t length) {
53 | if (length < 2) {
54 | return 0.0;
55 | }
56 |
57 | double sum = 0.0;
58 | for (size_t i = 0; i < length; i++) {
59 | sum += numbers[i];
60 | }
61 |
62 | double avg = sum / length;
63 | double sumOfSquares = 0.0;
64 | for (size_t i = 0; i < length; i++) {
65 | sumOfSquares += (numbers[i] - avg) * (numbers[i] - avg);
66 | }
67 |
68 | return sqrt(sumOfSquares / (length - 1));
69 | }
70 |
71 | int gcd(int a, int b) {
72 | return (b == 0) ? a : gcd(b, a % b);
73 | }
--------------------------------------------------------------------------------
/library/src/commonMain/cpp/hyperoperator.h:
--------------------------------------------------------------------------------
1 | #ifndef MORE_MATH_HYPEROPERATOR_H
2 | #define MORE_MATH_HYPEROPERATOR_H
3 |
4 | #include
5 |
6 | double tetraction(double number, int other);
7 | unsigned long factorial(int number);
8 | unsigned long factorial_(long number);
9 | double average(const int* number, size_t length);
10 | double standardDeviation(const double* numbers, size_t length);
11 | int gcd(int a, int b);
12 |
13 | #endif //MORE_MATH_HYPEROPERATOR_H
14 |
--------------------------------------------------------------------------------
/library/src/commonMain/cpp/nativelib.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "hyperoperator.h"
5 |
6 | extern "C" {
7 | JNIEXPORT jlong JNICALL
8 | Java_more_math_native_model_NativeProvider_cppFactorial(JNIEnv *env, jobject thiz, jint number) {
9 | return static_cast(factorial(number));
10 | }
11 | JNIEXPORT jlong JNICALL
12 | Java_more_math_native_model_NativeProvider_cppLongFactorial(JNIEnv *env, jobject thiz, jlong number) {
13 | return static_cast(factorial_(static_cast(number)));
14 | }
15 |
16 | JNIEXPORT jdouble JNICALL
17 | Java_more_math_native_model_NativeProvider_cppAverage(JNIEnv *env, jobject thiz,jintArray numbers) {
18 |
19 | jsize length = env->GetArrayLength(numbers);
20 | jint* elements = env->GetIntArrayElements(numbers, nullptr);
21 | if (elements == nullptr) {
22 | return 0.0;
23 | }
24 |
25 | double avg = average(elements, length);
26 |
27 | env->ReleaseIntArrayElements(numbers, elements, 0);
28 |
29 | return avg;
30 | }
31 |
32 | JNIEXPORT jdouble JNICALL
33 | Java_more_math_native_model_NativeProvider_cppStandardDeviation(JNIEnv *env, jobject thiz,
34 | jdoubleArray numbers) {
35 | jsize length = env->GetArrayLength(numbers);
36 |
37 | jdouble *elements = env->GetDoubleArrayElements(numbers, nullptr);
38 | if (elements == nullptr) {
39 | return 0.0;
40 | }
41 |
42 | double stddev = standardDeviation(elements, length);
43 |
44 | env->ReleaseDoubleArrayElements(numbers, elements, 0);
45 |
46 | return stddev;
47 | }
48 |
49 | JNIEXPORT jdouble JNICALL
50 | Java_more_math_native_model_NativeProvider_cppTetraction(JNIEnv *env, jobject thiz, jdouble number,
51 | jint other) {
52 | return tetraction(static_cast(number), static_cast(other));
53 | }
54 |
55 | JNIEXPORT jint JNICALL
56 | Java_more_math_native_model_NativeProvider_cppGcd(JNIEnv *env, jobject thiz, jint a, jint b) {
57 | return gcd(a, b);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/Annotations.kt:
--------------------------------------------------------------------------------
1 | package more.math
2 |
3 | @Target(
4 | AnnotationTarget.FUNCTION,
5 | AnnotationTarget.CLASS,
6 | AnnotationTarget.LOCAL_VARIABLE,
7 | AnnotationTarget.FIELD
8 | )
9 | @Retention(AnnotationRetention.RUNTIME)
10 | public annotation class ExperimentalApi public constructor(val reason: String = "Experimental API")
11 |
12 | @Target(
13 | AnnotationTarget.LOCAL_VARIABLE,
14 | AnnotationTarget.VALUE_PARAMETER
15 | )
16 | @Retention(AnnotationRetention.RUNTIME)
17 | public annotation class InProgress public constructor(val reason: String = "In progress")
18 |
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/Extensions.kt:
--------------------------------------------------------------------------------
1 | package more.math
2 |
3 | import more.math.complex.model.Complex
4 | import more.math.matrix.model.Matrix
5 | import more.math.vector.model.Vector2
6 |
7 | public inline fun matrixOf(vararg row: MutableList): Matrix {
8 | return Matrix(*row.map { it.toMutableList() }.toTypedArray())
9 | }
10 |
11 | //region::Vector
12 | public inline fun vector2Of(x: T, y: T): Vector2 {
13 | return Vector2(x, y)
14 | }
15 | //endregion
16 |
17 | //region::Complex
18 | public inline fun complex(
19 | realPart: R,
20 | imaginaryPart: Double
21 | ): Complex {
22 | return Complex(
23 | realPart = realPart,
24 | imaginaryPart = (if (imaginaryPart < 0) -1 else 1) * kotlin.math.sqrt(
25 | kotlin.math.abs(
26 | imaginaryPart
27 | )
28 | )
29 | )
30 | }
31 |
32 | public inline fun complex(
33 | imaginaryPart: Double
34 | ): Complex {
35 | return Complex(
36 | realPart = 0,
37 | imaginaryPart = (if (imaginaryPart < 0) -1 else 1) * kotlin.math.sqrt(
38 | kotlin.math.abs(
39 | imaginaryPart
40 | )
41 | )
42 | )
43 | }
44 | //endregion
45 |
46 | //region::Number
47 | public val Number.isPositive: Boolean
48 | get() = when (this) {
49 | is Int -> this.toInt() > 0
50 | is Double -> this.toDouble() > 0
51 | is Long -> this.toLong() > 0
52 | is Float -> this.toFloat() > 0
53 | else -> {
54 | throw IllegalArgumentException("Unknown type.")
55 | }
56 | }
57 |
58 | public val Number.isNegative: Boolean
59 | get() = when (this) {
60 | is Int -> this.toInt() < 0
61 | is Double -> this.toDouble() < 0
62 | is Long -> this.toLong() < 0
63 | is Float -> this.toFloat() < 0
64 | else -> {
65 | throw IllegalArgumentException("Unknown type.")
66 | }
67 | }
68 | //endregion
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/MoreMath.kt:
--------------------------------------------------------------------------------
1 | package more.math
2 |
3 | import more.math.combinatorics.CombinatoricsParent
4 | import more.math.factorial.FactorialParent
5 | import more.math.platform.model.BigFloat
6 | import more.math.platform.model.BigInt
7 | import more.math.native.model.NativeProvider
8 | import more.math.tetraction.TetractionParent
9 | import kotlin.math.pow
10 |
11 | public object MoreMath {
12 |
13 | private val factorialParent = FactorialParent()
14 | private val tetractionParent = TetractionParent()
15 | private val combinatoricsParent = CombinatoricsParent()
16 | private val nativeProvider = NativeProvider()
17 |
18 | //region::Algebra
19 | public fun factorial(n: Int): Long {
20 | factorialParent.verifyFactorial(n)
21 | return nativeProvider.nativeFactorial(number = n)
22 | }
23 |
24 | public fun factorial(n: Long): Long {
25 | factorialParent.verifyFactorial(n)
26 | return nativeProvider.nativeFactorial(number = n)
27 | }
28 |
29 | public fun bigFactorial(n: Long): BigInt {
30 | factorialParent.verifyPositive(n)
31 | if (n == 0L || n == 1L) {
32 | return BigInt(BigInt.ONE.toString())
33 | }
34 |
35 | val number = BigInt(n.toString())
36 | val result = number.multiply(bigFactorial(n - 1L))
37 |
38 | return BigInt(result.toString())
39 | }
40 |
41 | public fun tetraction(number: Double, other: Int): Double {
42 | tetractionParent.verify(number, other)
43 | return nativeProvider.tetraction(number, other)
44 | }
45 |
46 | public fun bigTetraction(number: Double, other: Int): BigFloat {
47 | tetractionParent.verify(number, other)
48 | return if (other == 0) {
49 | BigFloat(1.0.toString())
50 | } else {
51 | BigFloat(number.pow(tetraction(number, other - 1)).toString())
52 | }
53 | }
54 |
55 | public fun average(vararg numbers: Int): Double {
56 | return nativeProvider.nativeAverage(*numbers)
57 | }
58 |
59 | public fun standardDeviation(vararg numbers: Double): Double {
60 | return nativeProvider.standardDeviation(*numbers)
61 | }
62 |
63 | //Нок
64 | public fun gcd(a: Int, b: Int): Int {
65 | require(a >= 0 && b >= 0) { "Both numbers must be non-negative" }
66 | return nativeProvider.gcd(a = a, b = b)
67 | }
68 | //endregion
69 |
70 | //region::Combinatorics
71 | public fun combinations(n: Int, k: Int): Long {
72 | combinatoricsParent.verify(n, k)
73 | return factorial(n) / (factorial(k) * factorial(n - k))
74 | }
75 |
76 | public fun placements(n: Int, k: Int): Long {
77 | combinatoricsParent.verify(n, k)
78 | return factorial(n) / factorial(n - k)
79 | }
80 |
81 | public fun binomialCoefficient(n: Int, k: Int) : Long {
82 | combinatoricsParent.verify(n, k)
83 | return factorial(n) / (factorial(k) * factorial(n - k))
84 | }
85 | //endregion
86 | }
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/combinatorics/CombinatoricsParent.kt:
--------------------------------------------------------------------------------
1 | package more.math.combinatorics
2 |
3 | class CombinatoricsParent {
4 | fun verify(n: Int, k: Int) {
5 | require(n >= 0 && k >= 0 && k <= n) { "Number n must be >= 0, k must be >= 0 and k must be <= n." }
6 | }
7 | }
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/complex/model/Complex.kt:
--------------------------------------------------------------------------------
1 | package more.math.complex.model
2 |
3 | public data class Complex(val realPart: Number, val imaginaryPart: Double) {
4 |
5 | val modulus: Double
6 | get() = kotlin.math.hypot(realPart.toDouble(), imaginaryPart)
7 |
8 | val argument: Double
9 | get() = kotlin.math.atan2(imaginaryPart, realPart.toDouble())
10 |
11 | override fun toString(): String {
12 | return "Algebraic form is ${toAlgebraic()}, geometric form is ${toGeometric()}"
13 | }
14 |
15 | fun toGeometric(): String {
16 | return if (imaginaryPart >= 0) {
17 | "$modulus * (cos(${argument}) + i * sin(${argument}))"
18 | } else {
19 | "$modulus * (cos(${argument}) - i * sin(${argument}))"
20 | }
21 | }
22 |
23 | fun toAlgebraic(): String {
24 | return if (imaginaryPart >= 0) {
25 | "$realPart + ${imaginaryPart}i"
26 | } else {
27 | "$realPart - ${-imaginaryPart}i"
28 | }
29 | }
30 |
31 | operator fun plus(other: Complex): Complex {
32 | val realPartSum = when (this.realPart) {
33 | is Int -> this.realPart.toInt() + other.realPart.toInt()
34 | is Double -> this.realPart.toDouble() + other.realPart.toDouble()
35 | else -> throw IllegalArgumentException("Unknown realPart type")
36 | }
37 |
38 | return Complex(realPartSum, this.imaginaryPart + other.imaginaryPart)
39 | }
40 |
41 | operator fun minus(other: Complex): Complex {
42 | val realPartMinus = when (this.realPart) {
43 | is Int -> this.realPart.toInt() - other.realPart.toInt()
44 | is Double -> this.realPart.toDouble() - other.realPart.toDouble()
45 | else -> throw IllegalArgumentException("Unknown realPart type")
46 | }
47 |
48 | return Complex(realPartMinus, this.imaginaryPart - other.imaginaryPart)
49 | }
50 |
51 | operator fun times(other: Complex): Complex {
52 | val realPartMul = when (this.realPart) {
53 | is Int -> this.realPart.toInt() * other.realPart.toInt()
54 | is Double -> this.realPart.toDouble() * other.realPart.toDouble()
55 | else -> throw IllegalArgumentException("Unknown realPart type")
56 | }
57 |
58 | val realPartRes = when (realPartMul) {
59 | is Int -> realPartMul.toInt() - this.imaginaryPart * other.imaginaryPart
60 | is Double -> realPartMul.toDouble() - this.imaginaryPart * other.imaginaryPart
61 | else -> throw IllegalArgumentException("Unknown realPart type")
62 | }
63 |
64 | val imaginaryPartRes =
65 | this.realPart.toDouble() * other.imaginaryPart + this.imaginaryPart * other.realPart.toDouble()
66 |
67 | return Complex(realPartRes, imaginaryPartRes)
68 | }
69 |
70 | operator fun div(other: Complex): Complex {
71 | val thisReal = this.realPart.toDouble()
72 | val otherReal = other.realPart.toDouble()
73 |
74 | val denominator =
75 | otherReal * otherReal + other.imaginaryPart * other.imaginaryPart
76 | val realPart =
77 | (thisReal * otherReal + this.imaginaryPart * other.imaginaryPart) / denominator
78 | val imaginaryPart =
79 | (this.imaginaryPart * otherReal - thisReal * other.imaginaryPart) / denominator
80 |
81 | return Complex(realPart, imaginaryPart)
82 | }
83 |
84 | override fun equals(other: Any?): Boolean {
85 | if (this === other) return true
86 | if (other !is Complex) return false
87 |
88 | return this.realPart == other.realPart && this.imaginaryPart == other.imaginaryPart
89 | }
90 |
91 | override fun hashCode(): Int {
92 | var result = realPart.hashCode()
93 | result = 31 * result + imaginaryPart.hashCode()
94 | return result
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/factorial/FactorialParent.kt:
--------------------------------------------------------------------------------
1 | package more.math.factorial
2 |
3 | class FactorialParent {
4 | fun verifyFactorial(n: Int) {
5 | require(n in 0..20) {
6 | "Factorial must be in range 0..20."
7 | }
8 | }
9 |
10 | fun verifyFactorial(n: Long) {
11 | require(n in 0..20) {
12 | "Factorial must be in range 0..20."
13 | }
14 | }
15 |
16 | fun verifyPositive(n: Long) {
17 | require(n >= 0) {
18 | "Factorial must positive."
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/graph/model/Connection.kt:
--------------------------------------------------------------------------------
1 | package more.math.graph.model
2 |
3 | data class Connection(
4 | val from: Vertex,
5 | val to: Vertex,
6 | val weight: W
7 | ) {
8 | fun hasVertex(vertex: Vertex): Boolean {
9 | return from.id == vertex.id || to.id == vertex.id
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/graph/model/Graph.kt:
--------------------------------------------------------------------------------
1 | package more.math.graph.model
2 |
3 | import more.math.ExperimentalApi
4 | import more.math.graph.model.exception.NegativeWeightException
5 | import more.math.graph.model.exception.VertexNotFoundException
6 | import more.math.graph.model.mode.GraphMode
7 | import more.math.graph.model.mode.RemoveVertexMode
8 | import more.math.graph.model.mode.SetVertexMode
9 | import more.math.graph.parent.GraphParent
10 |
11 | @ExperimentalApi
12 | public class Graph
13 | public constructor(val mode: GraphMode = GraphMode.UNDIRECTED) : GraphParent() {
14 | val vertices: MutableList> = mutableListOf()
15 | val connections: MutableList> = mutableListOf()
16 | private var hasNegativeWeight: Boolean = false
17 |
18 | public fun addVertex(vertex: Vertex) {
19 | vertices.add(vertex)
20 | }
21 |
22 | public operator fun get(vertex: Vertex): Vertex? {
23 | return vertices.find { it.id == vertex.id }
24 | }
25 |
26 | public operator fun set(
27 | oldVertex: Vertex,
28 | newVertex: Vertex,
29 | setVertexMode: SetVertexMode
30 | ) {
31 | when (setVertexMode) {
32 | SetVertexMode.NEW_FROM -> {
33 | this.addVertex(vertex = newVertex)
34 | connections.forEachIndexed { index, item ->
35 | if (item.from.id == oldVertex.id) {
36 | connections[index] = connections[index].copy(from = newVertex)
37 | }
38 | }
39 | }
40 |
41 | SetVertexMode.NEW_TO -> {
42 | this.addVertex(vertex = newVertex)
43 | connections.forEachIndexed { index, item ->
44 | if (item.to.id == oldVertex.id) {
45 | connections[index] = connections[index].copy(to = newVertex)
46 | }
47 | }
48 | }
49 |
50 | SetVertexMode.NEW_FROM_TO -> {
51 | this.addVertex(vertex = newVertex)
52 | connections.forEachIndexed { index, item ->
53 | if (item.to.id == oldVertex.id) {
54 | connections[index] = connections[index].copy(to = newVertex)
55 | } else if (item.from.id == oldVertex.id) {
56 | connections[index] = connections[index].copy(from = newVertex)
57 | }
58 | }
59 | }
60 | }
61 | }
62 |
63 | public fun clearAllConnection() {
64 | connections.clear()
65 | }
66 |
67 | public fun clearAllVertices() {
68 | vertices.clear()
69 | }
70 |
71 | public fun removeConnectionsByVertex(vertex: Vertex, removeVertexMode: RemoveVertexMode) {
72 | when (removeVertexMode) {
73 | RemoveVertexMode.TO -> {
74 | connections.removeAll { it.to.id == vertex.id }
75 | }
76 |
77 | RemoveVertexMode.FROM -> {
78 | connections.removeAll { it.from.id == vertex.id }
79 | }
80 |
81 | RemoveVertexMode.BOTH -> {
82 | connections.removeAll { it.from.id == vertex.id || it.to.id == vertex.id }
83 | }
84 | }
85 | }
86 |
87 | public fun getFreeVertices(): List> {
88 | val free = mutableListOf>()
89 | vertices.forEach { vertex ->
90 | connections.forEach { connection ->
91 | if (!connection.hasVertex(vertex))
92 | free.add(vertex)
93 | }
94 | }
95 | return free.toList()
96 | }
97 |
98 | public fun getBusyVertices(): List> {
99 | val free = mutableListOf>()
100 | vertices.forEach { vertex ->
101 | connections.forEach { connection ->
102 | if (connection.hasVertex(vertex))
103 | free.add(vertex)
104 | }
105 | }
106 | return free.toList()
107 | }
108 |
109 | public fun createConnection(from: Vertex, to: Vertex, weight: W): Connection {
110 | val fromVertex = vertices.find { it.id == from.id }
111 | val toVertex = vertices.find { it.id == to.id }
112 | verify(vertices, from, to)
113 |
114 | hasNegativeWeight = when (weight) {
115 | is Int -> weight < 0
116 | is Long -> weight < 0
117 | is Double -> weight < 0
118 | is Float -> weight < 0
119 | else -> false
120 | }
121 |
122 | fromVertex!!
123 | toVertex!!
124 |
125 | val connection = Connection(from = fromVertex, to = toVertex, weight = weight)
126 | connections.add(connection)
127 | return connection
128 | }
129 |
130 | public fun minPath(from: Vertex, to: Vertex) : GraphPath {
131 | if (from !in vertices || to !in vertices) {
132 | throw VertexNotFoundException()
133 | }
134 |
135 | if (hasNegativeWeight) throw NegativeWeightException()
136 |
137 | val distances = mutableMapOf, Double>()
138 | val previousVertices = mutableMapOf, Vertex?>()
139 | val queue = vertices.toMutableList()
140 |
141 | vertices.forEach { vertex ->
142 | distances[vertex] = Double.MAX_VALUE
143 | previousVertices[vertex] = null
144 | }
145 | distances[from] = 0.0
146 |
147 | while (queue.isNotEmpty()) {
148 | val currentVertex = queue.minByOrNull { distances[it] ?: Double.MAX_VALUE }!!
149 | queue.remove(currentVertex)
150 |
151 | if (currentVertex == to) break
152 |
153 | connections.filter { it.from == currentVertex || (mode == GraphMode.UNDIRECTED && it.to == currentVertex) }.forEach { connection ->
154 | val neighbor = if (connection.from == currentVertex) connection.to else connection.from
155 | val newDist = distances[currentVertex]!! + connection.weight.toDouble()
156 |
157 | if (newDist < distances[neighbor]!!) {
158 | distances[neighbor] = newDist
159 | previousVertices[neighbor] = currentVertex
160 | }
161 | }
162 | }
163 |
164 | val path = mutableListOf, Double>>()
165 | var current: Vertex? = to
166 | while (current != null) {
167 | val weight = distances[current]
168 | path.add(Pair(current, weight!!))
169 | current = previousVertices[current]
170 | }
171 |
172 | return GraphPath(*path.reversed().toTypedArray())
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/graph/model/GraphPath.kt:
--------------------------------------------------------------------------------
1 | package more.math.graph.model
2 |
3 | class GraphPath constructor(
4 | vararg val path: Pair, W>
5 | )
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/graph/model/Vertex.kt:
--------------------------------------------------------------------------------
1 | package more.math.graph.model
2 |
3 | data class Vertex (
4 | val id: V
5 | )
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/graph/model/exception/NegativeWeightException.kt:
--------------------------------------------------------------------------------
1 | package more.math.graph.model.exception
2 |
3 | class NegativeWeightException : Exception() {
4 | override val message: String
5 | get() = "Negative weights in graph."
6 | }
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/graph/model/exception/VertexNotFoundException.kt:
--------------------------------------------------------------------------------
1 | package more.math.graph.model.exception
2 |
3 | class VertexNotFoundException : Exception() {
4 | override val message: String
5 | get() = "Vertex not found in graph."
6 | override val cause: Throwable?
7 | get() = super.cause
8 | }
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/graph/model/mode/GraphMode.kt:
--------------------------------------------------------------------------------
1 | package more.math.graph.model.mode
2 |
3 | enum class GraphMode {
4 | DIRECTED,
5 | UNDIRECTED
6 | }
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/graph/model/mode/RemoveVertexMode.kt:
--------------------------------------------------------------------------------
1 | package more.math.graph.model.mode
2 |
3 | enum class RemoveVertexMode {
4 | TO,
5 | FROM,
6 | BOTH
7 | }
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/graph/model/mode/SetVertexMode.kt:
--------------------------------------------------------------------------------
1 | package more.math.graph.model.mode
2 |
3 | enum class SetVertexMode {
4 | NEW_FROM,
5 | NEW_TO,
6 | NEW_FROM_TO,
7 | }
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/graph/parent/GraphParent.kt:
--------------------------------------------------------------------------------
1 | package more.math.graph.parent
2 |
3 | import more.math.graph.model.Vertex
4 |
5 | abstract class GraphParent {
6 | fun verify(list: List>, from: Vertex, to: Vertex) {
7 | val from_ = list.find { it.id == from.id }
8 | val to_ = list.find { it.id == to.id }
9 |
10 | require(from_ != null && to_ != null) {
11 | "Source or Destination Vertex not found"
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/matrix/model/Matrix.kt:
--------------------------------------------------------------------------------
1 | package more.math.matrix.model
2 |
3 | import more.math.matrix.parent.MatrixParent
4 |
5 | public class Matrix(vararg var rows: MutableList) : MatrixParent() {
6 |
7 | @Suppress("UNCHECKED_CAST")
8 | constructor(size: MatrixSize) : this(*Array(size.row) { MutableList(size.column) { null as R } }) {
9 | this.verifyMatrixSize(size = size)
10 | }
11 |
12 | init {
13 | this.verifyContent(*rows)
14 | }
15 |
16 | val size: MatrixSize = MatrixSize(row = rows.size, column = rows[0].size)
17 |
18 | fun column(columnIndex: Int): List {
19 | verifyColumn(this, columnIndex)
20 | val column: List = rows.map { it[columnIndex] }
21 | return column
22 | }
23 |
24 | operator fun get(rowIndex: Int, columnIndex: Int): R {
25 | verify(rows = rows, rowIndex = rowIndex, columnIndex = columnIndex)
26 | return rows[rowIndex][columnIndex]
27 | }
28 |
29 | operator fun set(rowIndex: Int, columnIndex: Int, item: R) {
30 | verify(rows = rows, rowIndex = rowIndex, columnIndex = columnIndex)
31 | rows[rowIndex][columnIndex] = item
32 | }
33 |
34 | @Suppress("UNCHECKED_CAST")
35 | operator fun plus(other: Matrix): Matrix {
36 | verifySize(rows = rows, other = other)
37 | val resultRows = Array(rows.size) { rowIndex ->
38 | List(rows[rowIndex].size) { columnIndex ->
39 |
40 | val unknownValueThis = this.rows[rowIndex][columnIndex]
41 | val thisValue = if (unknownValueThis is Int) {
42 | unknownValueThis
43 | } else {
44 | unknownValueThis as Double
45 | }
46 |
47 | val unknownValueOther = other.rows[rowIndex][columnIndex]
48 | val otherValue = if (unknownValueOther is Int) {
49 | unknownValueOther
50 | } else {
51 | unknownValueOther as Double
52 | }
53 |
54 | if (thisValue is Int && otherValue is Int) {
55 | (thisValue + otherValue) as R
56 | } else if (thisValue is Double && otherValue is Int) {
57 | (thisValue + otherValue) as R
58 | } else if (thisValue is Int && otherValue is Double) {
59 | (thisValue + otherValue) as R
60 | } else {
61 | thisValue as Double
62 | otherValue as Double
63 | (thisValue + otherValue) as R
64 | }
65 | }
66 | }
67 |
68 | return Matrix(*resultRows.map { it.toMutableList() }.toTypedArray())
69 | }
70 |
71 | @Suppress("UNCHECKED_CAST")
72 | operator fun minus(other: Matrix): Matrix {
73 | verifySize(rows = rows, other = other)
74 | val resultRows = Array(rows.size) { rowIndex ->
75 | List(rows[rowIndex].size) { columnIndex ->
76 |
77 | val unknownValueThis = this.rows[rowIndex][columnIndex]
78 | val thisValue = if (unknownValueThis is Int) {
79 | unknownValueThis
80 | } else {
81 | unknownValueThis as Double
82 | }
83 |
84 | val unknownValueOther = other.rows[rowIndex][columnIndex]
85 | val otherValue = if (unknownValueOther is Int) {
86 | unknownValueOther
87 | } else {
88 | unknownValueOther as Double
89 | }
90 |
91 | if (thisValue is Int && otherValue is Int) {
92 | (thisValue - otherValue) as R
93 | } else if (thisValue is Double && otherValue is Int) {
94 | (thisValue - otherValue) as R
95 | } else if (thisValue is Int && otherValue is Double) {
96 | (thisValue - otherValue) as R
97 | } else {
98 | thisValue as Double
99 | otherValue as Double
100 | (thisValue - otherValue) as R
101 | }
102 | }
103 | }
104 |
105 | return Matrix(*resultRows.map { it.toMutableList() }.toTypedArray())
106 | }
107 |
108 | operator fun compareTo(other: Matrix): Int {
109 | return this.size.compareTo(other.size)
110 | }
111 |
112 | @Suppress("UNCHECKED_CAST")
113 | operator fun times(other: Matrix): Matrix {
114 | verifyRows(rows = this.rows, other = other)
115 |
116 | val resultRows = Array(rows.size) { rowIndex ->
117 | List(other.rows[0].size) { columnIndex ->
118 | var sum = 0.0
119 | for (k in 0 until rows[0].size) {
120 |
121 | val unknownValueThis = this.rows[rowIndex][k]
122 | val thisValue = if (unknownValueThis is Int) {
123 | unknownValueThis
124 | } else {
125 | unknownValueThis as Double
126 | }
127 |
128 | val unknownValueOther = other.rows[k][columnIndex]
129 | val otherValue = if (unknownValueOther is Int) {
130 | unknownValueOther
131 | } else {
132 | unknownValueOther as Double
133 | }
134 |
135 | if (thisValue is Int && otherValue is Int) {
136 | sum += thisValue * otherValue
137 | } else if (thisValue is Double && otherValue is Int) {
138 | sum += thisValue * otherValue
139 | } else if (thisValue is Int && otherValue is Double) {
140 | sum += thisValue * otherValue
141 | } else {
142 | thisValue as Double
143 | otherValue as Double
144 | sum += thisValue * otherValue
145 | }
146 | }
147 | sum as R
148 | }
149 | }
150 | return Matrix(*resultRows.map { it.toMutableList() }.toTypedArray())
151 | }
152 |
153 | override fun toString(): String {
154 | return rows.joinToString("\n") { it.joinToString(" ") }
155 | }
156 |
157 | override fun equals(other: Any?): Boolean {
158 | if (this === other) return true
159 | if (other !is Matrix<*>) return false
160 |
161 | if (rows.size != other.rows.size || rows[0].size != other.rows[0].size) return false
162 |
163 | for (i in rows.indices) {
164 | if (rows[i] != other.rows[i]) return false
165 | }
166 | return true
167 | }
168 |
169 | override fun hashCode(): Int {
170 | var result = 1
171 | for (row in rows) {
172 | result = 31 * result + row.hashCode()
173 | }
174 | return result
175 | }
176 |
177 | fun find(predicate: (R) -> Boolean): R? {
178 | for (row in rows.indices) {
179 | for (column in rows[row].indices) {
180 | val el = rows[row][column]
181 | if (predicate(el)){
182 | return el
183 | }
184 | }
185 | }
186 | return null
187 | }
188 | }
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/matrix/model/MatrixExtension.kt:
--------------------------------------------------------------------------------
1 | package more.math.matrix.model
2 |
3 | import kotlin.math.pow
4 |
5 | //region::Other
6 | public fun Matrix.determinant(): Double {
7 | isSquare(matrix = this)
8 |
9 | if (rows.size == 1) {
10 | return this[0, 0].toDouble()
11 | }
12 | if (rows.size == 2) {
13 | return (this[0, 0].toDouble() * this[1, 1].toDouble() - this[0, 1].toDouble() * this[1, 0].toDouble())
14 | }
15 |
16 | var det = 0.0
17 | for (j in 0 until rows[0].size) {
18 | val minor = Matrix(*rows.indices.filter { it != 0 }.map { rowIndex ->
19 | rows[rowIndex].indices.filter { it != j }.map { colIndex ->
20 | this[rowIndex, colIndex]
21 | }.toMutableList()
22 | }.toTypedArray())
23 |
24 | det += (-1.0).pow(j) * this[0, j].toDouble() * minor.determinant()
25 | }
26 | return det
27 | }
28 |
29 | public fun Matrix.transpose(): Matrix {
30 | val transposedRows = Array(rows[0].size) { rowIndex ->
31 | List(rows.size) { colIndex ->
32 | this[colIndex, rowIndex]
33 | }
34 | }
35 | return Matrix(*transposedRows.map { it.toMutableList() }.toTypedArray())
36 | }
37 |
38 | public fun Matrix.pow(value: Int): Matrix {
39 | this.verifyMatrixPower(value)
40 | var resMatrix = this
41 | var power = value
42 | while (power > 1) {
43 | resMatrix *= resMatrix
44 | power -= 1
45 | }
46 | return resMatrix
47 | }
48 | //endregion
49 |
50 | //region::Times
51 | public fun Matrix.times(value: Int): Matrix {
52 | val map: List> = this.rows.map { rs ->
53 | val newRow = rs.map { item ->
54 | item.toInt() * value
55 | }
56 | newRow
57 | }
58 | return Matrix(*map.map { it.toMutableList() }.toTypedArray())
59 | }
60 |
61 | public fun Matrix.times(value: Double): Matrix {
62 | val map: List> = this.rows.map { rs ->
63 | val newRow = rs.map { item ->
64 | item.toDouble() * value
65 | }
66 | newRow
67 | }
68 | return Matrix(*map.map { it.toMutableList() }.toTypedArray())
69 | }
70 |
71 | public fun Matrix.times(value: Float): Matrix {
72 | val map: List> = this.rows.map { rs ->
73 | val newRow = rs.map { item ->
74 | item.toFloat() * value
75 | }
76 | newRow
77 | }
78 | return Matrix(*map.map { it.toMutableList() }.toTypedArray())
79 | }
80 |
81 | public fun Matrix.times(value: Long): Matrix {
82 | val map: List> = this.rows.map { rs ->
83 | val newRow = rs.map { item ->
84 | item.toLong() * value
85 | }
86 | newRow
87 | }
88 | return Matrix(*map.map { it.toMutableList() }.toTypedArray())
89 | }
90 | //endregion
91 |
92 | //region::Min in matrix
93 | public inline fun Matrix.minInMatrix(): Int {
94 | var globalMin: Int = Int.MAX_VALUE
95 | var min = 0
96 | this.rows.forEachIndexed { _, rs ->
97 | min = rs.minBy { it }
98 | if (min < globalMin) {
99 | globalMin = min
100 | }
101 | }
102 | return globalMin
103 | }
104 |
105 | public inline fun Matrix.minInMatrix(): Double {
106 | var globalMin: Double = Double.MAX_VALUE
107 | var min = 0.0
108 | this.rows.forEachIndexed { _, rs ->
109 | min = rs.minBy { it }
110 | if (min < globalMin) {
111 | globalMin = min
112 | }
113 | }
114 | return globalMin
115 | }
116 |
117 | public inline fun Matrix.minInMatrix(): Float {
118 | var globalMin: Float = Float.MAX_VALUE
119 | var min = 0.0f
120 | this.rows.forEachIndexed { _, rs ->
121 | min = rs.minBy { it }
122 | if (min < globalMin) {
123 | globalMin = min
124 | }
125 | }
126 | return globalMin
127 | }
128 |
129 | public inline fun Matrix.minInMatrix(): Long {
130 | var globalMin: Long = Long.MAX_VALUE
131 | var min = 0L
132 | this.rows.forEachIndexed { _, rs ->
133 | min = rs.minBy { it }
134 | if (min < globalMin) {
135 | globalMin = min
136 | }
137 | }
138 | return globalMin
139 | }
140 |
141 | public inline fun > Matrix.minInMatrixBy(block: (R) -> T): T {
142 | this.isEmpty(this)
143 |
144 | var minValue: T? = null
145 |
146 | for (row in rows) {
147 | for (element in row) {
148 | val transformedValue = block(element)
149 |
150 | if (minValue == null || transformedValue < minValue) {
151 | minValue = transformedValue
152 | }
153 | }
154 | }
155 |
156 | return minValue ?: throw IllegalStateException("Unable to find minimum value in the matrix.")
157 | }
158 | //endregion
159 |
160 | //region::Max in matrix
161 | public inline fun Matrix.maxInMatrix(): Int {
162 | var globalMax: Int = Int.MIN_VALUE
163 | var max = 0
164 | this.rows.forEachIndexed { _, rs ->
165 | max = rs.maxBy { it }
166 | if (max > globalMax) {
167 | globalMax = max
168 | }
169 | }
170 | return globalMax
171 | }
172 |
173 | public inline fun Matrix.maxInMatrix(): Double {
174 | var globalMax: Double = Double.MIN_VALUE
175 | var max = 0.0
176 | this.rows.forEachIndexed { _, rs ->
177 | max = rs.maxBy { it }
178 | if (max > globalMax) {
179 | globalMax = max
180 | }
181 | }
182 | return globalMax
183 | }
184 |
185 | public inline fun Matrix.maxInMatrix(): Float {
186 | var globalMax: Float = Float.MIN_VALUE
187 | var max = 0.0f
188 | this.rows.forEachIndexed { _, rs ->
189 | max = rs.maxBy { it }
190 | if (max > globalMax) {
191 | globalMax = max
192 | }
193 | }
194 | return globalMax
195 | }
196 |
197 | public inline fun Matrix.maxInMatrix(): Long {
198 | var globalMax: Long = Long.MIN_VALUE
199 | var max = 0L
200 | this.rows.forEachIndexed { _, rs ->
201 | max = rs.maxBy { it }
202 | if (max > globalMax) {
203 | globalMax = max
204 | }
205 | }
206 | return globalMax
207 | }
208 |
209 | public inline fun > Matrix.maxInMatrixBy(block: (R) -> T): T {
210 | this.isEmpty(this)
211 |
212 | var maxValue: T? = null
213 |
214 | for (row in rows) {
215 | for (element in row) {
216 | val transformedValue = block(element)
217 |
218 | if (maxValue == null || transformedValue > maxValue) {
219 | maxValue = transformedValue
220 | }
221 | }
222 | }
223 |
224 | return maxValue ?: throw IllegalStateException("Unable to find maximum value in the matrix.")
225 | }
226 | //endregion
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/matrix/model/MatrixSize.kt:
--------------------------------------------------------------------------------
1 | package more.math.matrix.model
2 |
3 | data class MatrixSize(
4 | val row: Int,
5 | val column: Int
6 | ) {
7 | operator fun compareTo(other: MatrixSize): Int {
8 | return (this.row * this.column).compareTo(other.row * other.column)
9 | }
10 |
11 | operator fun plus(other: MatrixSize): MatrixSize {
12 | return MatrixSize(row = this.row + other.row, column = this.column + other.column)
13 | }
14 |
15 | operator fun minus(other: MatrixSize): MatrixSize {
16 | return MatrixSize(row = this.row - other.row, column = this.column - other.column)
17 | }
18 |
19 | operator fun times(other: MatrixSize): MatrixSize {
20 | return MatrixSize(row = this.row * other.row, column = this.column * other.column)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/matrix/parent/MatrixParent.kt:
--------------------------------------------------------------------------------
1 | package more.math.matrix.parent
2 |
3 | import more.math.matrix.model.Matrix
4 | import more.math.matrix.model.MatrixSize
5 |
6 | abstract class MatrixParent {
7 | fun verify(rows: Array>, rowIndex: Int, columnIndex: Int) {
8 | require(rowIndex in rows.indices) { "Row index out of bounds." }
9 | require(columnIndex in rows[rowIndex].indices) { "Column index out of bounds." }
10 | }
11 |
12 | fun verifySize(rows: Array>, other: Matrix) {
13 | require(rows.size == other.rows.size && rows[0].size == other.rows[0].size) {
14 | "Matrices must have the same dimensions for addition."
15 | }
16 | }
17 |
18 | fun verifyRows(rows: Array>, other: Matrix) {
19 | require(rows.size == other.rows[0].size) {
20 | "Number of columns of the first matrix must be equal to the number of rows of the second matrix."
21 | }
22 | }
23 |
24 | fun isSquare(matrix: Matrix) {
25 | require(matrix.rows.size == matrix.rows[0].size) {
26 | "Number of rows must be equals number of columns."
27 | }
28 | }
29 |
30 | fun verifyColumn(matrix: Matrix, columnIndex: Int) {
31 | require(columnIndex in matrix.rows.indices) {
32 | "Column index is out of matrix size."
33 | }
34 | }
35 |
36 | fun verifyMatrixPower(power: Int) {
37 | require(power > 1) {
38 | "Power must be more than 1."
39 | }
40 | }
41 |
42 | fun isEmpty(matrix: Matrix) {
43 | require(matrix.rows.isNotEmpty() && matrix.rows[0].isNotEmpty()) { "Matrix cannot be empty." }
44 | }
45 |
46 | fun verifyContent(vararg rows: MutableList) {
47 | val rowSize = rows[0].size
48 | rows.forEachIndexed { _, rs ->
49 | require(rs.size == rowSize) {
50 | "Items in each row must be equals."
51 | }
52 | }
53 | }
54 |
55 | fun verifyMatrixSize(size: MatrixSize) {
56 | require(size.column > 0 && size.row > 0) {
57 | "Matrix size must be positive."
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/native/model/NativeProvider.kt:
--------------------------------------------------------------------------------
1 | package more.math.native.model
2 |
3 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
4 | internal expect class NativeProvider constructor() {
5 |
6 | //region::hyper operators
7 | fun nativeFactorial(number: Int): Long
8 |
9 | fun nativeFactorial(number: Long): Long
10 |
11 | fun nativeAverage(vararg numbers: Int) : Double
12 |
13 | fun standardDeviation(vararg numbers: Double) : Double
14 |
15 | fun tetraction(number: Double, other: Int) : Double
16 |
17 | fun gcd(a: Int, b: Int): Int
18 | //endregion
19 | }
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/platform/model/BigFloat.kt:
--------------------------------------------------------------------------------
1 | package more.math.platform.model
2 |
3 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
4 | expect class BigFloat(value: String) {
5 | companion object {
6 | val ZERO: BigFloat
7 | val ONE: BigFloat
8 | }
9 | fun add(other: BigFloat): BigFloat
10 | fun multiply(other: BigFloat): BigFloat
11 | override fun toString(): String
12 | }
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/platform/model/BigInt.kt:
--------------------------------------------------------------------------------
1 | package more.math.platform.model
2 |
3 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
4 | expect class BigInt(value: String) {
5 | companion object {
6 | val ZERO: BigInt
7 | val ONE: BigInt
8 | }
9 | fun add(other: BigInt): BigInt
10 | fun multiply(other: BigInt): BigInt
11 | override fun toString(): String
12 | }
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/tetraction/TetractionParent.kt:
--------------------------------------------------------------------------------
1 | package more.math.tetraction
2 |
3 | class TetractionParent {
4 | fun verify(number: Double, other: Int) {
5 | require(number >= 0 && other >= 0) {
6 | "Both arguments must be more than zero"
7 | }
8 | }
9 | }
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/vector/model/Vector2.kt:
--------------------------------------------------------------------------------
1 | package more.math.vector.model
2 |
3 | @Suppress("UNCHECKED_CAST")
4 | public data class Vector2(val x: T, val y: T) {
5 |
6 | operator fun plus(other: Vector2): Vector2 {
7 | return Vector2(
8 | x = when (x) {
9 | is Double -> (x.toDouble() + other.x.toDouble()) as T
10 | is Float -> (x.toFloat() + other.x.toFloat()) as T
11 | is Int -> (x.toInt() + other.x.toInt()) as T
12 | is Long -> (x.toLong() + other.x.toLong()) as T
13 | else -> throw IllegalArgumentException("Unsupported type")
14 | },
15 | y = when (y) {
16 | is Double -> (y.toDouble() + other.y.toDouble()) as T
17 | is Float -> (y.toFloat() + other.y.toFloat()) as T
18 | is Int -> (y.toInt() + other.y.toInt()) as T
19 | is Long -> (y.toLong() + other.y.toLong()) as T
20 | else -> throw IllegalArgumentException("Unsupported type")
21 | }
22 | )
23 | }
24 |
25 | operator fun minus(other: Vector2): Vector2 {
26 | return Vector2(
27 | x = when (x) {
28 | is Double -> (x.toDouble() - other.x.toDouble()) as T
29 | is Float -> (x.toFloat() - other.x.toFloat()) as T
30 | is Int -> (x.toInt() - other.x.toInt()) as T
31 | is Long -> (x.toLong() - other.x.toLong()) as T
32 | else -> throw IllegalArgumentException("Unsupported type")
33 | },
34 | y = when (y) {
35 | is Double -> (y.toDouble() - other.y.toDouble()) as T
36 | is Float -> (y.toFloat() - other.y.toFloat()) as T
37 | is Int -> (y.toInt() - other.y.toInt()) as T
38 | is Long -> (y.toLong() - other.y.toLong()) as T
39 | else -> throw IllegalArgumentException("Unsupported type")
40 | }
41 | )
42 | }
43 |
44 | operator fun times(other: Vector2): Vector2 {
45 | return Vector2(
46 | x = when (x) {
47 | is Double -> (x.toDouble() * other.x.toDouble()) as T
48 | is Float -> (x.toFloat() * other.x.toFloat()) as T
49 | is Int -> (x.toInt() * other.x.toInt()) as T
50 | is Long -> (x.toLong() * other.x.toLong()) as T
51 | else -> throw IllegalArgumentException("Unsupported type")
52 | },
53 | y = when (y) {
54 | is Double -> (y.toDouble() * other.y.toDouble()) as T
55 | is Float -> (y.toFloat() * other.y.toFloat()) as T
56 | is Int -> (y.toInt() * other.y.toInt()) as T
57 | is Long -> (y.toLong() * other.y.toLong()) as T
58 | else -> throw IllegalArgumentException("Unsupported type")
59 | }
60 | )
61 | }
62 |
63 | operator fun div(other: Vector2): Vector2 {
64 | return Vector2(
65 | x = when (x) {
66 | is Double -> (x.toDouble() / other.x.toDouble()) as T
67 | is Float -> (x.toFloat() / other.x.toFloat()) as T
68 | is Int -> (x.toInt() / other.x.toInt()) as T
69 | is Long -> (x.toLong() / other.x.toLong()) as T
70 | else -> throw IllegalArgumentException("Unsupported type")
71 | },
72 | y = when (y) {
73 | is Double -> (y.toDouble() / other.y.toDouble()) as T
74 | is Float -> (y.toFloat() / other.y.toFloat()) as T
75 | is Int -> (y.toInt() / other.y.toInt()) as T
76 | is Long -> (y.toLong() / other.y.toLong()) as T
77 | else -> throw IllegalArgumentException("Unsupported type")
78 | }
79 | )
80 | }
81 |
82 | override fun toString(): String {
83 | return "[x: $x; y: $y]"
84 | }
85 |
86 | override fun equals(other: Any?): Boolean {
87 | if (this === other) return true
88 | if (other !is Vector2<*>) return false
89 | return (x.toDouble() == other.x.toDouble() && y.toDouble() == other.y.toDouble())
90 | }
91 |
92 | // Переопределение hashCode
93 | override fun hashCode(): Int {
94 | var result = x.hashCode()
95 | result = 31 * result + y.hashCode()
96 | return result
97 | }
98 | }
--------------------------------------------------------------------------------
/library/src/commonMain/kotlin/more/math/vector/model/Vector2Extensions.kt:
--------------------------------------------------------------------------------
1 | package more.math.vector.model
2 |
3 | public fun Vector2.length(): Double {
4 | return kotlin.math.sqrt(this.x * this.x + this.y * this.y)
5 | }
--------------------------------------------------------------------------------
/library/src/commonTest/kotlin/more/math/ExtensionsKtTest.kt:
--------------------------------------------------------------------------------
1 | package more.math
2 |
3 | import kotlin.test.Test
4 | import kotlin.test.assertTrue
5 |
6 | class ExtensionsKtTest {
7 |
8 | @Test
9 | fun isPositiveOrNegative() {
10 | assertTrue(2.isPositive)
11 | assertTrue(2.0.isPositive)
12 | assertTrue(2.0f.isPositive)
13 | assertTrue(2L.isPositive)
14 |
15 | assertTrue((-2).isNegative)
16 | assertTrue((-2.0).isNegative)
17 | assertTrue((-2.0f).isNegative)
18 | assertTrue((-2L).isNegative)
19 | }
20 | }
--------------------------------------------------------------------------------
/library/src/commonTest/kotlin/more/math/combinatorics/CombinatoricsTest.kt:
--------------------------------------------------------------------------------
1 | package more.math.combinatorics
2 |
3 | import more.math.MoreMath
4 | import kotlin.test.Test
5 | import kotlin.test.assertEquals
6 | import kotlin.test.assertFails
7 |
8 | class CombinatoricsTest {
9 |
10 | @Test
11 | fun testCombinations() {
12 | assertEquals(1, MoreMath.combinations(0, 0))
13 | assertEquals(1, MoreMath.combinations(5, 0))
14 | assertEquals(10, MoreMath.combinations(5, 2))
15 | assertEquals(1, MoreMath.combinations(5, 5))
16 | assertEquals(1, MoreMath.combinations(5, 5))
17 | }
18 |
19 | @Test
20 | fun testPermutations() {
21 | assertEquals(1, MoreMath.placements(0, 0))
22 | assertEquals(5, MoreMath.placements(5, 1))
23 | assertEquals(20, MoreMath.placements(5, 2))
24 | assertEquals(120, MoreMath.placements(5, 5))
25 | }
26 |
27 | @Test
28 | fun testBinomialCoefficient() {
29 | assertEquals(1, MoreMath.binomialCoefficient(0, 0))
30 | assertEquals(1, MoreMath.binomialCoefficient(5, 0))
31 | assertEquals(10, MoreMath.binomialCoefficient(5, 2))
32 | assertEquals(1, MoreMath.binomialCoefficient(5, 5))
33 | }
34 |
35 | @Test
36 | fun testInvalidInputs() {
37 | assertFails {
38 | MoreMath.combinations(5, 6)
39 | }
40 | assertFails {
41 | MoreMath.placements(5, 6)
42 | }
43 | assertFails {
44 | MoreMath.binomialCoefficient(5, 6)
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/library/src/commonTest/kotlin/more/math/complex/model/ComplexTest.kt:
--------------------------------------------------------------------------------
1 | package more.math.complex.model
2 |
3 | import more.math.complex
4 | import kotlin.test.Test
5 | import kotlin.test.assertEquals
6 | import kotlin.test.assertTrue
7 |
8 | class ComplexTest {
9 |
10 | @Test
11 | fun creationOfComplexNumber() {
12 | val complex: Complex = complex(3, -4.0)
13 | assertEquals(3.0, complex.realPart.toDouble())
14 | assertEquals(-2.0, complex.imaginaryPart)
15 |
16 | val complex2 = complex( -4.0)
17 | assertEquals(-2.0, complex2.imaginaryPart)
18 | }
19 |
20 | @Test
21 | fun sumOfComplexNumbers() {
22 | val complex1 = complex(2, 9.0)
23 | val complex2 = complex(1, 16.0)
24 | val result = complex1 + complex2
25 | assertEquals(3.0, result.realPart.toDouble())
26 | assertEquals(7.0, result.imaginaryPart)
27 | }
28 |
29 | @Test
30 | fun minusOfComplexNumbers() {
31 | val complex1 = complex(5, 9.0)
32 | val complex2 = complex(2, 1.0)
33 | val result = complex1 - complex2
34 | assertEquals(3.0, result.realPart.toDouble())
35 | assertEquals(2.0, result.imaginaryPart)
36 | }
37 |
38 | @Test
39 | fun timeOfComplexNumbers() {
40 | val complex1 = complex(1, 4.0)
41 | val complex2 = complex(3, 16.0)
42 | val result = complex1 * complex2
43 | assertEquals(-5.0, result.realPart.toDouble())
44 | assertEquals(10.0, result.imaginaryPart)
45 | }
46 |
47 | @Test
48 | fun divisionOfComplexNumbers() {
49 | val complex1 = complex(1, 4.0)
50 | val complex2 = complex(3, 16.0)
51 | val result = complex1 / complex2
52 | assertEquals(0.44, result.realPart.toDouble(), 0.01)
53 | assertEquals(0.08, result.imaginaryPart, 0.01)
54 | }
55 |
56 | @Test
57 | fun testEquals() {
58 | val complex1 = complex(2, -4.0)
59 | val complex2 = complex(2, -4.0)
60 | assertTrue {
61 | complex1 == complex2
62 | }
63 | }
64 |
65 | @Test
66 | fun testAlgebraicForm() {
67 | assertEquals("2 - 3.0i", complex(2, -9.0).toAlgebraic())
68 | assertEquals("2 + 3.0i", complex(2, 9.0).toAlgebraic())
69 | }
70 |
71 | @Test
72 | fun testGeometricForm() {
73 | val complex = complex(3, 16.0)
74 | assertEquals("5.0 * (cos(0.9272952180016122) + i * sin(0.9272952180016122))", complex.toGeometric())
75 | }
76 | }
--------------------------------------------------------------------------------
/library/src/commonTest/kotlin/more/math/factorial/FactorialTest.kt:
--------------------------------------------------------------------------------
1 | package more.math.factorial
2 |
3 | import more.math.MoreMath
4 | import kotlin.test.Test
5 | import kotlin.test.assertEquals
6 | import kotlin.test.assertFails
7 |
8 | class FactorialTest {
9 |
10 | @Test
11 | fun testFactorial() {
12 | assertEquals(expected = 6L, actual = MoreMath.factorial(n = 3))
13 | assertEquals(expected = 1L, actual = MoreMath.factorial(n = 0))
14 | assertEquals(expected = 1L, actual = MoreMath.factorial(n = 1))
15 | assertEquals(expected = 6L, actual = MoreMath.factorial(n = 3L))
16 | }
17 |
18 | @Test
19 | fun testFactorialFails() {
20 | assertFails {
21 | MoreMath.factorial(n = -3)
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/library/src/commonTest/kotlin/more/math/graph/model/GraphTest.kt:
--------------------------------------------------------------------------------
1 | package more.math.graph.model
2 |
3 | import more.math.graph.model.mode.GraphMode
4 | import more.math.graph.model.mode.SetVertexMode
5 | import more.math.matrix.model.Matrix
6 | import more.math.matrixOf
7 | import kotlin.test.Test
8 | import kotlin.test.assertEquals
9 | import kotlin.test.assertFails
10 | import kotlin.test.assertNull
11 |
12 | class GraphTest {
13 |
14 | @Test
15 | fun testGraphFakeVertex() {
16 | val graph = Graph, Int>()
17 |
18 | val m1 = matrixOf(
19 | mutableListOf(1, 2),
20 | mutableListOf(3, 4)
21 | )
22 | val m2 = matrixOf(
23 | mutableListOf(5, 6),
24 | mutableListOf(7, 8)
25 | )
26 | val m3 = matrixOf(mutableListOf(0), mutableListOf(0))
27 |
28 | graph.addVertex(
29 | Vertex(
30 | id = m1
31 | )
32 | )
33 | graph.addVertex(
34 | Vertex(
35 | id = m2
36 | )
37 | )
38 |
39 | graph.createConnection(from = Vertex(id = m1), to = Vertex(id = m2), weight = 2)
40 | assertFails {
41 | graph.createConnection(Vertex(id = m1), Vertex(id = m3), weight = 3)
42 | }
43 |
44 | val vertex = graph[Vertex(id = m1)]
45 | assertEquals(
46 | expected = Vertex(id = m1),
47 | actual = vertex
48 | )
49 | assertEquals(expected = 2, actual = graph.vertices.size)
50 | }
51 |
52 | @Test
53 | fun get() {
54 | val graph = Graph()
55 |
56 | graph.addVertex(Vertex(id = "A"))
57 | graph.addVertex(Vertex(id = "B"))
58 |
59 | graph.createConnection(from = Vertex(id = "A"), to = Vertex(id = "B"), weight = 2)
60 |
61 | val vertex = graph[Vertex(id = "A")]
62 | assertEquals(
63 | expected = Vertex(id = "A"),
64 | actual = vertex
65 | )
66 | assertNull(graph[Vertex(id = "C")])
67 | }
68 |
69 | @Test
70 | fun sizes() {
71 | val graph = Graph()
72 |
73 | graph.addVertex(Vertex(id = "A"))
74 | graph.addVertex(Vertex(id = "B"))
75 |
76 | graph.createConnection(from = Vertex(id = "A"), to = Vertex(id = "B"), weight = 2)
77 |
78 | assertEquals(expected = 2, actual = graph.vertices.size)
79 | assertEquals(expected = 1, actual = graph.connections.size)
80 | }
81 |
82 | @Test
83 | fun testConnections() {
84 | val graph = Graph()
85 |
86 | graph.addVertex(Vertex(id = "A"))
87 | graph.addVertex(Vertex(id = "B"))
88 |
89 | graph.createConnection(from = Vertex(id = "A"), to = Vertex(id = "B"), weight = 2)
90 |
91 | assertEquals(expected = 1, actual = graph.connections.size)
92 | }
93 |
94 | @Test
95 | fun testSetVertexMode() {
96 | val graph = Graph()
97 |
98 | val vertexA = Vertex(id = "A")
99 | val vertexB = Vertex(id = "B")
100 | val vertexC = Vertex(id = "C")
101 | val vertexD = Vertex(id = "D")
102 |
103 | graph.addVertex(vertexA)
104 | graph.addVertex(vertexB)
105 | graph.addVertex(vertexD)
106 |
107 | graph.createConnection(from = vertexA, to = vertexB, weight = 2)
108 | graph.createConnection(from = vertexA, to = vertexD, weight = 5)
109 |
110 | graph.set(oldVertex = vertexA, newVertex = vertexC, setVertexMode = SetVertexMode.NEW_FROM)
111 |
112 | assertEquals(expected = vertexC, actual = graph[vertexC])
113 | assertEquals(expected = 2, actual = graph.connections.size)
114 |
115 | graph.set(oldVertex = vertexC, newVertex = vertexA, setVertexMode = SetVertexMode.NEW_TO)
116 |
117 | assertEquals(expected = vertexA, actual = graph[vertexA])
118 | assertEquals(expected = 2, actual = graph.connections.size)
119 |
120 | graph.createConnection(from = vertexD, to = vertexA, weight = 5)
121 | graph.createConnection(from = vertexA, to = vertexD, weight = 10)
122 |
123 | graph.set(
124 | oldVertex = vertexA,
125 | newVertex = vertexC,
126 | setVertexMode = SetVertexMode.NEW_FROM_TO
127 | )
128 |
129 | assertEquals(expected = vertexC, actual = graph[vertexC])
130 | assertEquals(expected = 4, actual = graph.connections.size)
131 | }
132 |
133 | @Test
134 | fun freeVertices() {
135 | val graph = Graph()
136 |
137 | val vertexA = Vertex(id = "A")
138 | val vertexB = Vertex(id = "B")
139 | val vertexC = Vertex(id = "C")
140 | val vertexD = Vertex(id = "D")
141 |
142 | graph.addVertex(vertexA)
143 | graph.addVertex(vertexB)
144 | graph.addVertex(vertexC)
145 | graph.addVertex(vertexD)
146 |
147 | graph.createConnection(from = vertexA, to = vertexB, weight = 2)
148 | assertEquals(expected = 2, graph.getFreeVertices().size)
149 | assertEquals(expected = 2, graph.getBusyVertices().size)
150 | }
151 |
152 | @Test
153 | fun testMinPathFunUndirectedGraph() {
154 | val graph = Graph(mode = GraphMode.UNDIRECTED)
155 |
156 | val vertexA = Vertex(id = "A")
157 | val vertexB = Vertex(id = "B")
158 | val vertexC = Vertex(id = "C")
159 | val vertexD = Vertex(id = "D")
160 | val vertexE = Vertex(id = "E")
161 |
162 | graph.addVertex(vertexA)
163 | graph.addVertex(vertexB)
164 | graph.addVertex(vertexC)
165 | graph.addVertex(vertexD)
166 | graph.addVertex(vertexE)
167 |
168 | graph.createConnection(from = vertexA, to = vertexB, weight = 2)
169 | graph.createConnection(from = vertexB, to = vertexC, weight = 5)
170 | graph.createConnection(from = vertexC, to = vertexD, weight = 6)
171 | graph.createConnection(from = vertexA, to = vertexD, weight = 17)
172 |
173 | val minPath1: GraphPath = graph.minPath(from = vertexA, to = vertexD)
174 | val expected1 = GraphPath(
175 | Pair(vertexA, 0.0),
176 | Pair(vertexB, 2.0),
177 | Pair(vertexC, 7.0),
178 | Pair(vertexD, 13.0),
179 | )
180 | assertEquals(expected = expected1.path[2], actual = minPath1.path[2])
181 |
182 | graph.createConnection(from = vertexB, to = vertexE, weight = 1)
183 | graph.createConnection(from = vertexE, to = vertexD, weight = 3)
184 |
185 | val minPath2: GraphPath = graph.minPath(from = vertexA, to = vertexD)
186 | val expected2 = GraphPath(
187 | Pair(vertexA, 0.0),
188 | Pair(vertexB, 2.0),
189 | Pair(vertexE, 3.0),
190 | Pair(vertexD, 6.0),
191 | )
192 | assertEquals(expected = expected2.path[2].second, actual = minPath2.path[2].second)
193 |
194 | graph.createConnection(from = vertexE, to = vertexA, weight = -3)
195 | assertFails {
196 | graph.minPath(from = vertexA, to = vertexD)
197 | }
198 | }
199 | }
--------------------------------------------------------------------------------
/library/src/commonTest/kotlin/more/math/matrix/model/MatrixExtensionKtTest.kt:
--------------------------------------------------------------------------------
1 | package more.math.matrix.model
2 |
3 | import more.math.complex
4 | import more.math.complex.model.Complex
5 | import more.math.matrixOf
6 | import kotlin.test.BeforeTest
7 | import kotlin.test.Test
8 | import kotlin.test.assertEquals
9 | import kotlin.test.assertFails
10 | import kotlin.test.assertNull
11 | import kotlin.test.assertTrue
12 | import kotlin.test.assertTrue
13 |
14 | class MatrixExtensionKtTest {
15 |
16 | private lateinit var matrix: Matrix
17 |
18 | @BeforeTest
19 | fun setUp() {
20 | matrix = matrixOf(
21 | mutableListOf(1, 2.5, 3),
22 | mutableListOf(4.0, 5, 6)
23 | )
24 | }
25 |
26 | @Test
27 | fun testMatrixFunctions() {
28 | val number: Number = matrix[0, 0]
29 | assertEquals(expected = 1, actual = number)
30 | }
31 |
32 | @Test
33 | fun sumMatrix() {
34 | val matrix1 = matrixOf(
35 | mutableListOf(1, 2, 3),
36 | mutableListOf(4, 5, 6)
37 | )
38 |
39 | val matrix2 = Matrix(
40 | mutableListOf(7, 8, 9),
41 | mutableListOf(10, 11, 12)
42 | )
43 |
44 | val sumMatrix = matrix1 + matrix2
45 |
46 | val expectedMatrix = matrixOf(
47 | mutableListOf(8, 10, 12),
48 | mutableListOf(14, 16, 18)
49 | )
50 |
51 | assertEquals(expected = expectedMatrix, actual = sumMatrix)
52 | }
53 |
54 | @Test
55 | fun minusTest() {
56 | val matrix1 = matrixOf(
57 | mutableListOf(1, 2, 3),
58 | mutableListOf(4, 5, 6)
59 | )
60 |
61 | val matrix2 = Matrix(
62 | mutableListOf(7, 8, 9),
63 | mutableListOf(10, 11, 12)
64 | )
65 |
66 | val minusMatrix = matrix1 - matrix2
67 |
68 | val expectedMatrix = matrixOf(
69 | mutableListOf(-6, -6, -6),
70 | mutableListOf(-6, -6, -6)
71 | )
72 |
73 | assertEquals(expected = expectedMatrix, actual = minusMatrix)
74 | }
75 |
76 | @Test
77 | fun timesTest() {
78 | val matrix1 = matrixOf(
79 | mutableListOf(1.0, 2.0, 3.0),
80 | mutableListOf(4.0, 5.0, 6.0)
81 | )
82 |
83 | val matrix2 = Matrix(
84 | mutableListOf(7.0, 8.0),
85 | mutableListOf(9.0, 10.0),
86 | mutableListOf(11.0, 12.0)
87 | )
88 |
89 | val timesMatrix = matrix1 * matrix2
90 |
91 | val expectedMatrix = matrixOf(
92 | mutableListOf(58.0, 64.0),
93 | mutableListOf(139.0, 154.0)
94 | )
95 |
96 | assertEquals(expected = expectedMatrix, actual = timesMatrix)
97 | }
98 |
99 | @Test
100 | fun squareDeterminant() {
101 | val matrix = matrixOf(
102 | mutableListOf(1.0, 2.0),
103 | mutableListOf(3.0, 4.0)
104 | )
105 |
106 | val determinant = matrix.determinant()
107 |
108 | assertEquals(expected = -2.0, actual = determinant)
109 | }
110 |
111 | @Test
112 | fun squareBigDeterminant() {
113 | val matrix = matrixOf(
114 | mutableListOf(1.0, 2.0, 3.0, 4.0),
115 | mutableListOf(5.0, 6.0, 7.0, 8.0),
116 | mutableListOf(9.0, 10.0, 11.0, 12.0),
117 | mutableListOf(13.0, 14.0, 15.0, 16.0),
118 | )
119 |
120 | val determinant = matrix.determinant()
121 |
122 | assertEquals(expected = 0.0, actual = determinant)
123 | }
124 |
125 | @Test
126 | fun transposeTest() {
127 | val matrix1 = matrixOf(
128 | mutableListOf(1, 2, 3),
129 | mutableListOf(4, 5, 6)
130 | ).transpose()
131 |
132 | val expected = matrixOf(
133 | mutableListOf(1, 4),
134 | mutableListOf(2, 5),
135 | mutableListOf(3, 6)
136 | )
137 |
138 | assertEquals(expected = expected, actual = matrix1)
139 | }
140 |
141 | @Test
142 | fun testFails() {
143 | assertFails {
144 | matrix[99, 1]
145 | }
146 | assertFails {
147 | matrix[1, 99]
148 | }
149 | assertFails {
150 | val matrix1 = matrixOf(
151 | mutableListOf(1, 2, 3),
152 | mutableListOf(4, 5, 6)
153 | )
154 | val matrix2 = matrixOf(
155 | mutableListOf(1, 4),
156 | mutableListOf(2, 5),
157 | mutableListOf(3, 6)
158 | )
159 | matrix1 + matrix2
160 | }
161 | assertFails {
162 | val matrix1 = matrixOf(
163 | mutableListOf(1, 2, 3),
164 | mutableListOf(4, 5, 6)
165 | )
166 | val matrix2 = matrixOf(
167 | mutableListOf(1, 4),
168 | mutableListOf(2, 5),
169 | mutableListOf(3, 6)
170 | )
171 | matrix1 - matrix2
172 | }
173 |
174 | assertFails {
175 | val matrix1 = matrixOf(
176 | mutableListOf(1, 2),
177 | mutableListOf(3, 4),
178 | mutableListOf(5, 6),
179 | mutableListOf(7, 8)
180 | )
181 | val matrix2 = matrixOf(
182 | mutableListOf(1, 4),
183 | mutableListOf(2, 5),
184 | mutableListOf(3, 6)
185 | )
186 | matrix1 * matrix2
187 | }
188 | assertFails {
189 | matrix.determinant()
190 | }
191 | }
192 |
193 | @Test
194 | fun timesByNumber() {
195 | val matrixInt = Matrix(
196 | mutableListOf(1, 2),
197 | mutableListOf(3, 4)
198 | )
199 | val matrixDouble = Matrix(
200 | mutableListOf(1.0, 2.0),
201 | mutableListOf(3.0, 4.0)
202 | )
203 |
204 | val resMatrix1 = Matrix(
205 | mutableListOf(2, 4),
206 | mutableListOf(6, 8)
207 | )
208 | val resMatrix2 = Matrix(
209 | mutableListOf(2.0, 4.0),
210 | mutableListOf(6.0, 8.0)
211 | )
212 |
213 | assertEquals(expected = matrixInt.times(2), actual = resMatrix1)
214 | assertEquals(expected = matrixDouble.times(2.0), actual = resMatrix2)
215 | }
216 |
217 | @Test
218 | fun columnTest() {
219 | val matrixInt = Matrix(
220 | mutableListOf(1, 2, 3),
221 | mutableListOf(4, 5, 6),
222 | mutableListOf(7, 8, 9)
223 | )
224 | assertEquals(mutableListOf(1, 4, 7), matrixInt.column(0))
225 | assertEquals(mutableListOf(2, 5, 8), matrixInt.column(1))
226 | assertEquals(mutableListOf(3, 6, 9), matrixInt.column(2))
227 | assertFails {
228 | matrixInt.column(4)
229 | matrixInt.column(-4)
230 | }
231 | }
232 |
233 | @Test
234 | fun testPowMatrix() {
235 | val matrixDouble = Matrix(
236 | mutableListOf(1.0, 2.0),
237 | mutableListOf(3.0, 4.0)
238 | )
239 | val matrixDoubleRes = Matrix(
240 | mutableListOf(7.0, 10.0),
241 | mutableListOf(15.0, 22.0)
242 | )
243 |
244 | assertEquals(expected = matrixDoubleRes, actual = matrixDouble.pow(2))
245 | }
246 |
247 | @Test
248 | fun minItemInMatrix() {
249 | val matrix1 = matrixOf(
250 | mutableListOf(1, 2),
251 | mutableListOf(3, 4),
252 | mutableListOf(-1, -2),
253 | )
254 |
255 | val min1 = matrix1.minInMatrix()
256 | assertEquals(expected = -2, actual = min1)
257 |
258 | val matrix2 = matrixOf(
259 | mutableListOf(1f, 2f),
260 | mutableListOf(3f, 4f),
261 | mutableListOf(-1f, -2f),
262 | )
263 |
264 | val min2 = matrix2.minInMatrix()
265 | assertEquals(expected = -2f, actual = min2)
266 |
267 | val matrix3 = matrixOf(
268 | mutableListOf(1L, 2L),
269 | mutableListOf(3L, 4L),
270 | mutableListOf(-1L, -2L),
271 | )
272 |
273 | val min3 = matrix3.minInMatrix()
274 | assertEquals(expected = -2L, actual = min3)
275 |
276 | val matrix4 = matrixOf(
277 | mutableListOf(1.0, 2.0),
278 | mutableListOf(3.0, 4.0),
279 | mutableListOf(-1.0, -2.0),
280 | )
281 |
282 | val min4 = matrix4.minInMatrix()
283 | assertEquals(expected = -2.0, actual = min4)
284 |
285 | val matrix5 = matrixOf(
286 | mutableListOf(complex(3, -16.0), complex(3, -4.0)),
287 | mutableListOf(complex(3, 25.0), complex(3, -36.0)),
288 | mutableListOf(complex(3, -49.0), complex(3, 36.0)),
289 | )
290 |
291 | assertEquals(expected = -7.0, actual = matrix5.minInMatrixBy { it.imaginaryPart })
292 | }
293 |
294 | @Test
295 | fun maxItemInMatrix() {
296 | val matrix5 = matrixOf(
297 | mutableListOf(complex(3, -16.0), complex(3, -4.0)),
298 | mutableListOf(complex(3, 25.0), complex(3, -36.0)),
299 | mutableListOf(complex(3, -49.0), complex(3, 36.0)),
300 | )
301 | assertEquals(expected = 6.0, actual = matrix5.maxInMatrixBy { it.imaginaryPart })
302 | }
303 |
304 | @Test
305 | fun strMatrix() {
306 | val matrix = matrixOf(
307 | mutableListOf("a", "b"),
308 | mutableListOf("c", "d")
309 | )
310 | assertEquals(expected = "a", actual = matrix[0, 0])
311 |
312 | val matrix2 = matrixOf(
313 | mutableListOf(
314 | Complex(realPart = 1, imaginaryPart = -16.0),
315 | Complex(realPart = 2, imaginaryPart = -16.0)
316 | ),
317 | mutableListOf(
318 | Complex(realPart = 3, imaginaryPart = -16.0),
319 | Complex(realPart = 4, imaginaryPart = -16.0)
320 | )
321 | )
322 | assertEquals(
323 | expected = Complex(realPart = 1, imaginaryPart = -16.0),
324 | actual = matrix2[0, 0]
325 | )
326 |
327 | assertFails {
328 | val sum = matrix + matrix
329 | val sum2 = matrix2 + matrix2
330 | }
331 | }
332 |
333 | @Test
334 | fun set() {
335 | val matrix1 = matrixOf(
336 | mutableListOf(1, 2, 3),
337 | mutableListOf(4, 5, 6)
338 | )
339 | val matrix2 = matrixOf(
340 | mutableListOf(1, 2, 3),
341 | mutableListOf(4, -1, 6)
342 | )
343 | matrix1[1, 1] = -1
344 | assertEquals(matrix1, matrix2)
345 | }
346 |
347 | @Test
348 | fun matrixSize() {
349 | val matrix = matrixOf(
350 | mutableListOf(1, 2, 3),
351 | mutableListOf(4, 5, 6)
352 | )
353 |
354 | val size = matrix.size
355 |
356 | assertEquals(MatrixSize(2, 3), size)
357 | }
358 |
359 | @Test
360 | fun verifyContent() {
361 | assertFails {
362 | matrixOf(
363 | mutableListOf(1, 2, 3),
364 | mutableListOf(4, 5, 6),
365 | mutableListOf(7, 8, 9, 10, 11)
366 | )
367 |
368 | matrixOf(
369 | mutableListOf(7, 8, 9, 10, 11),
370 | mutableListOf(1, 2, 3),
371 | mutableListOf(4, 5, 6)
372 | )
373 |
374 | matrixOf(
375 | mutableListOf("1", "1", "1", "1"),
376 | mutableListOf(4, 5, 6)
377 | )
378 | }
379 | }
380 |
381 | @Test
382 | fun matrixSizeWithConstructor() {
383 | val matrix1 = Matrix(size = MatrixSize(row = 3, column = 4))
384 | val matrix2 = Matrix(size = MatrixSize(row = 1, column = 1))
385 |
386 | assertEquals(expected = matrix1.size, actual = MatrixSize(3, 4))
387 | assertFails { matrix1[1, 1] as Int}
388 | assertEquals(expected = matrix2.rows.size, 1)
389 | assertFails {
390 | Matrix(size = MatrixSize(row = -3, column = -4))
391 | }
392 | }
393 |
394 | @Test
395 | fun compareTo() {
396 | val matrix1 = matrixOf(
397 | mutableListOf(1, 2, 3),
398 | mutableListOf(4, 5, 6),
399 | mutableListOf(7, 8, 9),
400 | )
401 | val matrix2 = matrixOf(
402 | mutableListOf(1, 2),
403 | mutableListOf(3, 4)
404 | )
405 | val matrix3 = matrixOf(
406 | mutableListOf(1, 2),
407 | mutableListOf(3, 4)
408 | )
409 |
410 | val m1 = MatrixSize(1, 1)
411 | val m2 = MatrixSize(1, 2)
412 | val m3 = MatrixSize(1, 2)
413 |
414 | assertTrue(m1 < m2)
415 | assertTrue(m1 != m2)
416 | assertEquals(m2, m3)
417 |
418 | assertTrue(matrix1 > matrix2)
419 | assertTrue(matrix1 != matrix2)
420 | assertEquals(matrix2, matrix3)
421 | }
422 |
423 | @Test
424 | fun findInMatrix() {
425 | val matrix1 = matrixOf(
426 | mutableListOf(1, 2, 3),
427 | mutableListOf(4, 5, 6),
428 | mutableListOf(7, 8, 9),
429 | )
430 | val e1: Int? = matrix1.find {
431 | it > 3
432 | }
433 | val e2: Int? = matrix1.find {
434 | it == 9
435 | }
436 | val e3: Int? = matrix1.find {
437 | it > 10
438 | }
439 | val e4: Int? = matrix1.find {
440 | (it in 21..49) || (it % 2 == 0 && it / 3 > 8) || (it == 30)
441 | }
442 |
443 | assertEquals(4, e1)
444 | assertEquals(9, e2)
445 | assertNull(e3)
446 | assertNull(e4)
447 | }
448 | }
449 |
--------------------------------------------------------------------------------
/library/src/commonTest/kotlin/more/math/other/OtherTest.kt:
--------------------------------------------------------------------------------
1 | package more.math.other
2 |
3 | import more.math.MoreMath
4 | import kotlin.test.Test
5 | import kotlin.test.assertEquals
6 | import kotlin.test.assertFails
7 |
8 | class OtherTest {
9 | @Test
10 | fun testGCD() {
11 | assertEquals(6, MoreMath.gcd(48, 18))
12 | assertEquals(1, MoreMath.gcd(13, 17))
13 | assertEquals(12, MoreMath.gcd(36, 60))
14 | assertEquals(0, MoreMath.gcd(0, 0))
15 | }
16 |
17 | @Test
18 | fun testGCDNegativeInputs() {
19 | assertFails {
20 | MoreMath.gcd(-10, 5)
21 | }
22 | assertFails {
23 | MoreMath.gcd(10, -5)
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/library/src/commonTest/kotlin/more/math/platform/MoreMathPlatformSpecificTest.kt:
--------------------------------------------------------------------------------
1 | package more.math.platform
2 |
3 | import more.math.MoreMath
4 | import more.math.platform.model.BigFloat
5 | import more.math.platform.model.BigInt
6 | import kotlin.test.Test
7 | import kotlin.test.assertEquals
8 |
9 | class MoreMathPlatformSpecificTest {
10 |
11 | @Test
12 | fun bigFactorial() {
13 | val n = 22L
14 | val result = MoreMath.bigFactorial(n)
15 | assertEquals(
16 | expected = BigInt("1124000727777607680000").toString(),
17 | actual = result.toString()
18 | )
19 | }
20 |
21 | @Test
22 | fun bigTetractionTest() {
23 | val result = MoreMath.bigTetraction(number = 2.0, other = 3)
24 | assertEquals(expected = BigFloat("16.0").toString(), actual = result.toString())
25 | }
26 | }
--------------------------------------------------------------------------------
/library/src/commonTest/kotlin/more/math/tetraction/TetractionTest.kt:
--------------------------------------------------------------------------------
1 | package more.math.tetraction
2 |
3 | import more.math.MoreMath
4 | import kotlin.test.Test
5 | import kotlin.test.assertEquals
6 |
7 | class TetractionTest {
8 | @Test
9 | fun tetractionTest() {
10 | val result = MoreMath.tetraction(number = 2.0, other = 3)
11 | assertEquals(expected = 16.0, actual = result)
12 | }
13 | }
--------------------------------------------------------------------------------
/library/src/commonTest/kotlin/more/math/vector/model/Vector2Test.kt:
--------------------------------------------------------------------------------
1 | package more.math.vector.model
2 |
3 | import more.math.vector2Of
4 | import kotlin.test.Test
5 | import kotlin.test.assertEquals
6 |
7 | class Vector2Test {
8 |
9 | @Test
10 | fun plusTest() {
11 | val vector1 = vector2Of(1, 2)
12 | val vector2 = vector2Of(3, 4)
13 |
14 | val res = vector1 + vector2
15 | assertEquals(expected = Vector2(x = 4, y = 6), actual = res)
16 | }
17 |
18 | @Test
19 | fun minusTest() {
20 | val vector1 = vector2Of(1, 2)
21 | val vector2 = vector2Of(3, 4)
22 |
23 | val res = vector1 - vector2
24 | assertEquals(expected = Vector2(x = -2, y = -2), actual = res)
25 | }
26 |
27 | @Test
28 | fun timesTest() {
29 | val vector1 = vector2Of(1, 2)
30 | val vector2 = vector2Of(3, 4)
31 |
32 | val res = vector1 * vector2
33 | assertEquals(expected = Vector2(x = 3, y = 8), actual = res)
34 | }
35 |
36 | @Test
37 | fun divTest() {
38 | val vector1 = vector2Of(1, 2)
39 | val vector2 = vector2Of(3, 4)
40 |
41 | val res = vector1 / vector2
42 | assertEquals(expected = Vector2(x = 1/3, y = 1/2), actual = res)
43 | }
44 |
45 | @Test
46 | fun length() {
47 | val vector1 = vector2Of(8.0, 6.0)
48 |
49 | val res = vector1.length()
50 | assertEquals(expected = 10.0, actual = res)
51 | }
52 | }
--------------------------------------------------------------------------------
/library/src/iosMain/kotlin/more/math/native/model/NativeProvider.ios.kt:
--------------------------------------------------------------------------------
1 | package more.math.native.model
2 |
3 | import more.math.MoreMath
4 | import kotlin.math.pow
5 |
6 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
7 | internal actual class NativeProvider actual constructor() {
8 |
9 | actual fun nativeFactorial(number: Int): Long {
10 | return if (number == 0) 1L else number * nativeFactorial(number - 1)
11 | }
12 |
13 | actual fun nativeFactorial(number: Long): Long {
14 | return if (number == 0L) 1L else number * nativeFactorial(number - 1)
15 | }
16 |
17 | actual fun nativeAverage(vararg numbers: Int): Double {
18 | return numbers.average()
19 | }
20 |
21 | actual fun standardDeviation(vararg numbers: Double) : Double {
22 | val avg = numbers.average()
23 | val sumOfSquares = numbers.sumOf { (it - avg) * (it - avg) }
24 | return kotlin.math.sqrt(sumOfSquares / (numbers.size - 1))
25 | }
26 |
27 | actual fun tetraction(number: Double, other: Int) : Double {
28 | return if (other == 0) {
29 | 1.0
30 | } else {
31 | number.pow(tetraction(number, other - 1))
32 | }
33 | }
34 |
35 | actual fun gcd(a: Int, b: Int): Int {
36 | return if (b == 0) a else MoreMath.gcd(b, a % b)
37 | }
38 | }
--------------------------------------------------------------------------------
/library/src/iosMain/kotlin/more/math/platform/model/BigFloat.ios.kt:
--------------------------------------------------------------------------------
1 | package more.math.platform.model
2 |
3 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
4 | actual class BigFloat actual constructor(value: String) {
5 | private val integerPart: BigInt
6 | private val fractionalPart: BigInt
7 |
8 | init {
9 | val parts = value.split(".")
10 | integerPart = BigInt(parts[0])
11 | fractionalPart = if (parts.size > 1) BigInt(parts[1]) else BigInt("0")
12 | }
13 |
14 | actual companion object {
15 | actual val ZERO: BigFloat get() = BigFloat("0.0")
16 | actual val ONE: BigFloat get() = BigFloat("1.0")
17 | }
18 |
19 | actual fun add(other: BigFloat): BigFloat {
20 | val sumInteger = integerPart.add(other.integerPart)
21 | val sumFractional = fractionalPart.add(other.fractionalPart)
22 |
23 | return if (sumFractional.toString().length > fractionalPart.toString().length) {
24 | val newInteger = sumInteger.add(BigInt("1"))
25 | val newFractional = BigInt("0")
26 | BigFloat("$newInteger.$newFractional")
27 | } else {
28 | BigFloat("$sumInteger.$sumFractional")
29 | }
30 | }
31 |
32 | actual fun multiply(other: BigFloat): BigFloat {
33 | val productInteger = integerPart.multiply(other.integerPart)
34 | val productFractional = fractionalPart.multiply(other.fractionalPart)
35 |
36 | val combinedFractional = productInteger.add(
37 | productFractional
38 | )
39 |
40 | return BigFloat("$combinedFractional.0")
41 | }
42 |
43 | actual override fun toString(): String {
44 | return "$integerPart.$fractionalPart"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/library/src/iosMain/kotlin/more/math/platform/model/BigInt.ios.kt:
--------------------------------------------------------------------------------
1 | package more.math.platform.model
2 |
3 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
4 | actual class BigInt actual constructor(value: String) {
5 |
6 | private val digits: List = value.reversed().map { it.digitToInt() }
7 |
8 | actual companion object {
9 | actual val ZERO: BigInt
10 | get() = BigInt("0")
11 | actual val ONE: BigInt
12 | get() = BigInt("1")
13 | }
14 |
15 | actual fun add(other: BigInt): BigInt {
16 | val maxLength = maxOf(this.digits.size, other.digits.size)
17 | val result = MutableList(maxLength + 1) { 0 }
18 | var carry = 0
19 |
20 | for (i in 0 until maxLength) {
21 | val thisDigit = if (i < this.digits.size) this.digits[i] else 0
22 | val otherDigit = if (i < other.digits.size) other.digits[i] else 0
23 | val sum = thisDigit + otherDigit + carry
24 | result[i] = sum % 10
25 | carry = sum / 10
26 | }
27 |
28 | if (carry > 0) {
29 | result[maxLength] = carry
30 | }
31 |
32 | return BigInt(result.reversed().dropWhile { it == 0 }.joinToString("") { it.toString() }
33 | .ifEmpty { "0" })
34 | }
35 |
36 | actual fun multiply(other: BigInt): BigInt {
37 | val result = MutableList(this.digits.size + other.digits.size) { 0 }
38 |
39 | for (i in this.digits.indices) {
40 | for (j in other.digits.indices) {
41 | val product = this.digits[i] * other.digits[j]
42 | result[i + j] += product
43 | }
44 | }
45 |
46 | for (i in result.indices) {
47 | if (result[i] >= 10) {
48 | val carry = result[i] / 10
49 | result[i] %= 10
50 | if (i + 1 < result.size) {
51 | result[i + 1] += carry
52 | } else {
53 | result.add(carry)
54 | }
55 | }
56 | }
57 |
58 | return BigInt(result.reversed().dropWhile { it == 0 }.joinToString("") { it.toString() }
59 | .ifEmpty { "0" })
60 | }
61 |
62 | actual override fun toString(): String {
63 | return digits.reversed().joinToString("") { it.toString() }.ifEmpty { "0" }
64 | }
65 | }
--------------------------------------------------------------------------------
/library/src/iosTest/kotlin/more/math/MoreMathTest.kt:
--------------------------------------------------------------------------------
1 | package more.math
2 |
3 | import more.math.matrix.model.Matrix
4 | import more.math.matrix.model.determinant
5 | import more.math.matrix.model.transpose
6 | import more.math.vector.model.Vector2
7 | import kotlin.test.Test
8 | import kotlin.test.assertEquals
9 |
10 | class MoreMathTest {
11 |
12 | @Test
13 | fun test() {
14 | val matrix = matrixOf(
15 | listOf(1,2),
16 | listOf(3,4),
17 | )
18 | val vector1 = vector2Of(1, 2)
19 | val vector2 = vector2Of(3, 4)
20 |
21 | assertEquals(expected = -2.0, actual = matrix.determinant())
22 | assertEquals(expected = 6, MoreMath.factorial(3))
23 | assertEquals(expected = 2.0, MoreMath.average(1, 2, 3))
24 | assertEquals(expected = Matrix(listOf(1, 3), listOf(2, 4)), matrix.transpose())
25 | assertEquals(expected = 16.0, MoreMath.tetraction(2.0, 3))
26 | assertEquals(expected = Vector2(x = 4, y = 6), actual = (vector1 + vector2))
27 | }
28 | }
--------------------------------------------------------------------------------
/library/src/iosTest/kotlin/more/math/platform/model/Factorial_iosKtTest.kt:
--------------------------------------------------------------------------------
1 | package more.math.platform.model
2 |
3 | import more.math.MoreMath
4 | import kotlin.test.Test
5 | import kotlin.test.assertEquals
6 |
7 | class Factorial_iosKtTest {
8 |
9 | @Test
10 | fun bigFactorial() {
11 | val n = 22L
12 | val result = MoreMath.bigFactorial(n)
13 | assertEquals(
14 | expected = BigInt("1124000727777607680000").toString(),
15 | actual = result.toString()
16 | )
17 | }
18 | }
--------------------------------------------------------------------------------
/library/src/jvmMain/kotlin/more/math/native/model/NativeProvider.jvm.kt:
--------------------------------------------------------------------------------
1 | package more.math.native.model
2 |
3 | import more.math.MoreMath
4 | import kotlin.math.pow
5 |
6 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
7 | internal actual class NativeProvider actual constructor() {
8 |
9 | actual fun nativeFactorial(number: Int): Long {
10 | return if (number == 0) 1L else number * nativeFactorial(number - 1)
11 | }
12 |
13 | //endregion
14 | actual fun nativeFactorial(number: Long): Long {
15 | return if (number == 0L) 1L else number * nativeFactorial(number - 1)
16 | }
17 |
18 | actual fun nativeAverage(vararg numbers: Int): Double {
19 | return numbers.average()
20 | }
21 |
22 | actual fun standardDeviation(vararg numbers: Double) : Double {
23 | val avg = numbers.average()
24 | val sumOfSquares = numbers.sumOf { (it - avg) * (it - avg) }
25 | return kotlin.math.sqrt(sumOfSquares / (numbers.size - 1))
26 | }
27 |
28 | actual fun tetraction(number: Double, other: Int) : Double {
29 | return if (other == 0) {
30 | 1.0
31 | } else {
32 | number.pow(tetraction(number, other - 1))
33 | }
34 | }
35 |
36 | actual fun gcd(a: Int, b: Int): Int {
37 | return if (b == 0) a else MoreMath.gcd(b, a % b)
38 | }
39 | }
--------------------------------------------------------------------------------
/library/src/jvmMain/kotlin/more/math/platform/model/BigFloat.jvm.kt:
--------------------------------------------------------------------------------
1 | package more.math.platform.model
2 |
3 | import java.math.BigDecimal
4 |
5 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
6 | actual class BigFloat actual constructor(value: String) {
7 | actual companion object {
8 | actual val ZERO: BigFloat get() = BigFloat(BigDecimal.ZERO.toString())
9 | actual val ONE: BigFloat get() = BigFloat(BigDecimal.ONE.toString())
10 | }
11 |
12 | private val bigFloat = BigDecimal(value)
13 |
14 | actual fun add(other: BigFloat): BigFloat {
15 | return BigFloat(this.bigFloat.add(other.bigFloat).toString())
16 | }
17 |
18 | actual fun multiply(other: BigFloat): BigFloat {
19 | return BigFloat(this.bigFloat.multiply(other.bigFloat).toString())
20 | }
21 |
22 | actual override fun toString(): String {
23 | return this.bigFloat.toString()
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/library/src/jvmMain/kotlin/more/math/platform/model/BigInt.jvm.kt:
--------------------------------------------------------------------------------
1 | package more.math.platform.model
2 |
3 | import java.math.BigInteger
4 |
5 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
6 | actual class BigInt actual constructor(value: String) {
7 |
8 | actual companion object {
9 | actual val ZERO: BigInt
10 | get() = BigInt("0")
11 | actual val ONE: BigInt
12 | get() = BigInt("1")
13 | }
14 |
15 | private val bigInt = BigInteger(value)
16 |
17 | actual fun add(other: BigInt): BigInt {
18 | return BigInt(this.bigInt.add(other.bigInt).toString())
19 | }
20 |
21 | actual fun multiply(other: BigInt): BigInt {
22 | return BigInt(this.bigInt.multiply(other.bigInt).toString())
23 | }
24 |
25 | actual override fun toString(): String {
26 | return this.bigInt.toString()
27 | }
28 | }
--------------------------------------------------------------------------------
/library/src/jvmTest/kotlin/more/math/MoreMathTest.kt:
--------------------------------------------------------------------------------
1 | package more.math
2 |
3 | import more.math.matrix.model.Matrix
4 | import more.math.matrix.model.determinant
5 | import more.math.matrix.model.transpose
6 | import more.math.vector.model.Vector2
7 | import kotlin.test.Test
8 | import kotlin.test.assertEquals
9 |
10 | class MoreMathTest {
11 |
12 | @Test
13 | fun test() {
14 | val matrix = matrixOf(
15 | mutableListOf(1,2),
16 | mutableListOf(3,4),
17 | )
18 | val vector1 = vector2Of(1, 2)
19 | val vector2 = vector2Of(3, 4)
20 |
21 | assertEquals(expected = -2.0, actual = matrix.determinant())
22 | assertEquals(expected = 6, MoreMath.factorial(3))
23 | assertEquals(expected = 2.0, MoreMath.average(1, 2, 3))
24 | assertEquals(expected = Matrix(mutableListOf(1, 3), mutableListOf(2, 4)), matrix.transpose())
25 | assertEquals(expected = 16.0, MoreMath.tetraction(2.0, 3))
26 | assertEquals(expected = Vector2(x = 4, y = 6), actual = (vector1 + vector2))
27 | }
28 | }
--------------------------------------------------------------------------------
/library/src/jvmTest/kotlin/more/math/platform/model/Factorial_jvmKtTest.kt:
--------------------------------------------------------------------------------
1 | package more.math.platform.model
2 |
3 | import more.math.MoreMath
4 | import kotlin.test.Test
5 | import kotlin.test.assertEquals
6 |
7 | class Factorial_jvmKtTest {
8 |
9 | @Test
10 | fun bigFactorial() {
11 | val n = 22L
12 | val result = MoreMath.bigFactorial(n)
13 | assertEquals(expected = BigInt("1124000727777607680000").toString(), actual = result.toString())
14 | }
15 | }
--------------------------------------------------------------------------------
/library/src/linuxX64Main/kotlin/more/math/native/model/NativeProvider.linuxX64.kt:
--------------------------------------------------------------------------------
1 | package more.math.native.model
2 |
3 | import more.math.MoreMath
4 | import kotlin.math.pow
5 |
6 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
7 | internal actual class NativeProvider actual constructor() {
8 |
9 | actual fun nativeFactorial(number: Int): Long {
10 | return if (number == 0) 1L else number * nativeFactorial(number - 1)
11 | }
12 |
13 | actual fun nativeFactorial(number: Long): Long {
14 | return if (number == 0L) 1L else number * nativeFactorial(number - 1)
15 | }
16 |
17 | actual fun nativeAverage(vararg numbers: Int): Double {
18 | return numbers.average()
19 | }
20 |
21 | actual fun standardDeviation(vararg numbers: Double) : Double {
22 | val avg = numbers.average()
23 | val sumOfSquares = numbers.sumOf { (it - avg) * (it - avg) }
24 | return kotlin.math.sqrt(sumOfSquares / (numbers.size - 1))
25 | }
26 |
27 | actual fun tetraction(number: Double, other: Int) : Double {
28 | return if (other == 0) {
29 | 1.0
30 | } else {
31 | number.pow(tetraction(number, other - 1))
32 | }
33 | }
34 |
35 | actual fun gcd(a: Int, b: Int): Int {
36 | return if (b == 0) a else MoreMath.gcd(b, a % b)
37 | }
38 | }
--------------------------------------------------------------------------------
/library/src/linuxX64Main/kotlin/more/math/platform/model/BigFloat.linuxX64.kt:
--------------------------------------------------------------------------------
1 | package more.math.platform.model
2 |
3 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
4 | actual class BigFloat actual constructor(value: String) {
5 | private val integerPart: BigInt
6 | private val fractionalPart: BigInt
7 |
8 | init {
9 | val parts = value.split(".")
10 | integerPart = BigInt(parts[0])
11 | fractionalPart = if (parts.size > 1) BigInt(parts[1]) else BigInt("0")
12 | }
13 |
14 | actual companion object {
15 | actual val ZERO: BigFloat get() = BigFloat("0.0")
16 | actual val ONE: BigFloat get() = BigFloat("1.0")
17 | }
18 |
19 | actual fun add(other: BigFloat): BigFloat {
20 | val sumInteger = integerPart.add(other.integerPart)
21 | val sumFractional = fractionalPart.add(other.fractionalPart)
22 |
23 | return if (sumFractional.toString().length > fractionalPart.toString().length) {
24 | val newInteger = sumInteger.add(BigInt("1"))
25 | val newFractional = BigInt("0")
26 | BigFloat("$newInteger.$newFractional")
27 | } else {
28 | BigFloat("$sumInteger.$sumFractional")
29 | }
30 | }
31 |
32 | actual fun multiply(other: BigFloat): BigFloat {
33 | val productInteger = integerPart.multiply(other.integerPart)
34 | val productFractional = fractionalPart.multiply(other.fractionalPart)
35 |
36 | val combinedFractional = productInteger.add(
37 | productFractional
38 | )
39 |
40 | return BigFloat("$combinedFractional.0")
41 | }
42 |
43 | actual override fun toString(): String {
44 | return "$integerPart.$fractionalPart"
45 | }
46 | }
--------------------------------------------------------------------------------
/library/src/linuxX64Main/kotlin/more/math/platform/model/BigInt.linuxX64.kt:
--------------------------------------------------------------------------------
1 | package more.math.platform.model
2 |
3 | @Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
4 | actual class BigInt actual constructor(value: String) {
5 | actual companion object {
6 | actual val ZERO: BigInt
7 | get() = BigInt("0")
8 | actual val ONE: BigInt
9 | get() = BigInt("1")
10 | }
11 |
12 | private val digits: List = value.reversed().map { it.digitToInt() }
13 |
14 | actual fun add(other: BigInt): BigInt {
15 | val maxLength = maxOf(this.digits.size, other.digits.size)
16 | val result = MutableList(maxLength + 1) { 0 }
17 | var carry = 0
18 |
19 | for (i in 0 until maxLength) {
20 | val thisDigit = if (i < this.digits.size) this.digits[i] else 0
21 | val otherDigit = if (i < other.digits.size) other.digits[i] else 0
22 | val sum = thisDigit + otherDigit + carry
23 | result[i] = sum % 10
24 | carry = sum / 10
25 | }
26 |
27 | if (carry > 0) {
28 | result[maxLength] = carry
29 | }
30 |
31 | return BigInt(result.reversed().dropWhile { it == 0 }.joinToString("") { it.toString() }
32 | .ifEmpty { "0" })
33 | }
34 |
35 | actual fun multiply(other: BigInt): BigInt {
36 | val result = MutableList(this.digits.size + other.digits.size) { 0 }
37 |
38 | for (i in this.digits.indices) {
39 | for (j in other.digits.indices) {
40 | val product = this.digits[i] * other.digits[j]
41 | result[i + j] += product
42 | }
43 | }
44 |
45 | for (i in result.indices) {
46 | if (result[i] >= 10) {
47 | val carry = result[i] / 10
48 | result[i] %= 10
49 | if (i + 1 < result.size) {
50 | result[i + 1] += carry
51 | } else {
52 | result.add(carry)
53 | }
54 | }
55 | }
56 |
57 | return BigInt(result.reversed().dropWhile { it == 0 }.joinToString("") { it.toString() }
58 | .ifEmpty { "0" })
59 | }
60 |
61 | actual override fun toString(): String {
62 | return digits.reversed().joinToString("") { it.toString() }.ifEmpty { "0" }
63 | }
64 | }
--------------------------------------------------------------------------------
/library/src/linuxX64Test/kotlin/more/math/MoreMathTest.kt:
--------------------------------------------------------------------------------
1 | package more.math
2 |
3 | import more.math.matrix.model.Matrix
4 | import more.math.matrix.model.determinant
5 | import more.math.matrix.model.transpose
6 | import more.math.vector.model.Vector2
7 | import kotlin.test.Test
8 | import kotlin.test.assertEquals
9 |
10 | class MoreMathTest {
11 |
12 | @Test
13 | fun test() {
14 | val matrix = matrixOf(
15 | listOf(1,2),
16 | listOf(3,4),
17 | )
18 | val vector1 = vector2Of(1, 2)
19 | val vector2 = vector2Of(3, 4)
20 |
21 | assertEquals(expected = -2.0, actual = matrix.determinant())
22 | assertEquals(expected = 6, MoreMath.factorial(3))
23 | assertEquals(expected = 2.0, MoreMath.average(1, 2, 3))
24 | assertEquals(expected = Matrix(listOf(1, 3), listOf(2, 4)), matrix.transpose())
25 | assertEquals(expected = 16.0, MoreMath.tetraction(2.0, 3))
26 | assertEquals(expected = Vector2(x = 4, y = 6), actual = (vector1 + vector2))
27 | }
28 | }
--------------------------------------------------------------------------------
/library/src/linuxX64Test/kotlin/more/math/platform/model/Factorial_linuxX64KtTest.kt:
--------------------------------------------------------------------------------
1 | package more.math.platform.model
2 |
3 | import more.math.MoreMath
4 | import kotlin.test.Test
5 | import kotlin.test.assertEquals
6 |
7 | class Factorial_linuxX64KtTest {
8 |
9 | @Test
10 | fun bigFactorial() {
11 | val n = 22L
12 | val result = MoreMath.bigFactorial(n)
13 | assertEquals(
14 | expected = BigInt("1124000727777607680000").toString(),
15 | actual = result.toString()
16 | )
17 | }
18 | }
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | gradlePluginPortal()
6 | }
7 | }
8 |
9 | dependencyResolutionManagement {
10 | repositories {
11 | google()
12 | mavenCentral()
13 | }
14 | }
15 |
16 | rootProject.name = "more-math"
17 | include(":library")
18 |
--------------------------------------------------------------------------------