diff --git a/.gitignore b/.gitignore index 6f44278..5c48bf2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,7 @@ *.pyc -.vscode \ No newline at end of file +.vscode +.idea/ + +*.c + +*.so diff --git a/Pipfile b/Pipfile index 111d4db..1f441bd 100644 --- a/Pipfile +++ b/Pipfile @@ -6,6 +6,7 @@ name = "pypi" [packages] numpy = "*" pandas = "*" +cython = "*" [dev-packages] diff --git a/Pipfile.lock b/Pipfile.lock index 0d84c13..af59c3d 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "b883be20349a56066666bdb40b43b81bd8af31c5b981137388600154591c7351" + "sha256": "79ddb27bf6f5e6aedfbf302b825eef67f73de68547f8081fc3a5eda70ce19d6d" }, "pipfile-spec": 6, "requires": { @@ -16,72 +16,118 @@ ] }, "default": { - "numpy": { + "cython": { "hashes": [ - "sha256:004f0efcb2fe1c0bd6ae1fcfc69cc8b6bf2407e0f18be308612007a0762b4089", - "sha256:09f6b7bdffe57fc61d869a22f506049825d707b288039d30f26a0d0d8ea05164", - "sha256:0ea3f98a0ffce3f8f57675eb9119f3f4edb81888b6874bc1953f91e0b1d4f440", - "sha256:17c0e467ade9bda685d5ac7f5fa729d8d3e76b23195471adae2d6a6941bd2c18", - "sha256:1f27b5322ac4067e67c8f9378b41c746d8feac8bdd0e0ffede5324667b8a075c", - "sha256:22d43376ee0acd547f3149b9ec12eec2f0ca4a6ab2f61753c5b29bb3e795ac4d", - "sha256:2ad3ec9a748a8943e6eb4358201f7e1c12ede35f510b1a2221b70af4bb64295c", - "sha256:301c00cf5e60e08e04d842fc47df641d4a181e651c7135c50dc2762ffe293dbd", - "sha256:39a664e3d26ea854211867d20ebcc8023257c1800ae89773cbba9f9e97bae036", - "sha256:51bf49c0cd1d52be0a240aa66f3458afc4b95d8993d2d04f0d91fa60c10af6cd", - "sha256:78a63d2df1d947bd9d1b11d35564c2f9e4b57898aae4626638056ec1a231c40c", - "sha256:7cd1328e5bdf0dee621912f5833648e2daca72e3839ec1d6695e91089625f0b4", - "sha256:8355fc10fd33a5a70981a5b8a0de51d10af3688d7a9e4a34fcc8fa0d7467bb7f", - "sha256:8c79d7cf86d049d0c5089231a5bcd31edb03555bd93d81a16870aa98c6cfb79d", - "sha256:91b8d6768a75247026e951dce3b2aac79dc7e78622fc148329135ba189813584", - "sha256:94c15ca4e52671a59219146ff584488907b1f9b3fc232622b47e2cf832e94fb8", - "sha256:98dcbc02e39b1658dc4b4508442a560fe3ca5ca0d989f0df062534e5ca3a5c1a", - "sha256:a64403f634e5ffdcd85e0b12c08f04b3080d3e840aef118721021f9b48fc1460", - "sha256:bc6e8da415f359b578b00bcfb1d08411c96e9a97f9e6c7adada554a0812a6cc6", - "sha256:bdc9febce3e68b697d931941b263c59e0c74e8f18861f4064c1f712562903411", - "sha256:c1ba66c48b19cc9c2975c0d354f24058888cdc674bebadceb3cdc9ec403fb5d1", - "sha256:c9f707b5bb73bf277d812ded9896f9512a43edff72712f31667d0a8c2f8e71ee", - "sha256:d5422d6a1ea9b15577a9432e26608c73a78faf0b9039437b075cf322c92e98e7", - "sha256:e5d5420053bbb3dd64c30e58f9363d7a9c27444c3648e61460c1237f9ec3fa14", - "sha256:e868b0389c5ccfc092031a861d4e158ea164d8b7fdbb10e3b5689b4fc6498df6", - "sha256:efd9d3abe5774404becdb0748178b48a218f1d8c44e0375475732211ea47c67e", - "sha256:f8c02ec3c4c4fcb718fdf89a6c6f709b14949408e8cf2a2be5bfa9c49548fd85", - "sha256:ffcf105ecdd9396e05a8e58e81faaaf34d3f9875f137c7372450baa5d77c9a54" + "sha256:061e25151c38f2361bc790d3bcf7f9d9828a0b6a4d5afa56fbed3bd33fb2373a", + "sha256:06be83490c906b6429b4389e13487a26254ccaad2eef6f3d4ee21d8d3a4aaa2b", + "sha256:07d173d3289415bb496e72cb0ddd609961be08fe2968c39094d5712ffb78672b", + "sha256:0bbc27abdf6aebfa1bce34cd92bd403070356f28b0ecb3198ff8a182791d58b9", + "sha256:0ea8267fc373a2c5064ad77d8ff7bf0ea8b88f7407098ff51829381f8ec1d5d9", + "sha256:3875c2b2ea752816a4d7ae59d45bb546e7c4c79093c83e3ba7f4d9051dd02928", + "sha256:39afb4679b8c6bf7ccb15b24025568f4f9b4d7f9bf3cbd981021f542acecd75b", + "sha256:3f85eb2343d20d91a4ea9cf14e5748092b376a64b7e07fc224e85b2753e9070b", + "sha256:40eff7aa26e91cf108fd740ffd4daf49f39b2fdffadabc7292b4b7dc5df879f0", + "sha256:479690d2892ca56d34812fe6ab8f58e4b2e0129140f3d94518f15993c40553da", + "sha256:4a4b03ab483271f69221c3210f7cde0dcc456749ecf8243b95bc7a701e5677e0", + "sha256:513e9707407608ac0d306c8b09d55a28be23ea4152cbd356ceaec0f32ef08d65", + "sha256:5514f3b4122cb22317122a48e175a7194e18e1803ca555c4c959d7dfe68eaf98", + "sha256:5ba622326f2862f9c1f99ca8d47ade49871241920a352c917e16861e25b0e5c3", + "sha256:63b79d9e1f7c4d1f498ab1322156a0d7dc1b6004bf981a8abda3f66800e140cd", + "sha256:656dc5ff1d269de4d11ee8542f2ffd15ab466c447c1f10e5b8aba6f561967276", + "sha256:67fdd2f652f8d4840042e2d2d91e15636ba2bcdcd92e7e5ffbc68e6ef633a754", + "sha256:79e3bab19cf1b021b613567c22eb18b76c0c547b9bc3903881a07bfd9e7e64cf", + "sha256:856d2fec682b3f31583719cb6925c6cdbb9aa30f03122bcc45c65c8b6f515754", + "sha256:8669cadeb26d9a58a5e6b8ce34d2c8986cc3b5c0bfa77eda6ceb471596cb2ec3", + "sha256:8733cf4758b79304f2a4e39ebfac5e92341bce47bcceb26c1254398b2f8c1af7", + "sha256:97335b2cd4acebf30d14e2855d882de83ad838491a09be2011745579ac975833", + "sha256:afbce249133a830f121b917f8c9404a44f2950e0e4f5d1e68f043da4c2e9f457", + "sha256:b0595aee62809ba353cebc5c7978e0e443760c3e882e2c7672c73ffe46383673", + "sha256:b6da3063c5c476f5311fd76854abae6c315f1513ef7d7904deed2e774623bbb9", + "sha256:c8e8025f496b5acb6ba95da2fb3e9dacffc97d9a92711aacfdd42f9c5927e094", + "sha256:cddc47ec746a08603037731f5d10aebf770ced08666100bd2cdcaf06a85d4d1b", + "sha256:cdf10af3e2e3279dc09fdc5f95deaa624850a53913f30350ceee824dc14fc1a6", + "sha256:d968ffc403d92addf20b68924d95428d523436adfd25cf505d427ed7ba3bee8b", + "sha256:dbee03b8d42dca924e6aa057b836a064c769ddfd2a4c2919e65da2c8a362d528", + "sha256:e1958e0227a4a6a2c06fd6e35b7469de50adf174102454db397cec6e1403cce3", + "sha256:e6ffa08aa1c111a1ebcbd1cf4afaaec120bc0bbdec3f2545f8bb7d3e8e77a1cd", + "sha256:e83228e0994497900af954adcac27f64c9a57cd70a9ec768ab0cb2c01fd15cf1", + "sha256:ea1dcc07bfb37367b639415333cfbfe4a93c3be340edf1db10964bc27d42ed64", + "sha256:eca3065a1279456e81c615211d025ea11bfe4e19f0c5650b859868ca04b3fcbd", + "sha256:ed087eeb88a8cf96c60fb76c5c3b5fb87188adee5e179f89ec9ad9a43c0c54b3", + "sha256:eeb475eb6f0ccf6c039035eb4f0f928eb53ead88777e0a760eccb140ad90930b", + "sha256:eefd2b9a5f38ded8d859fe96cc28d7d06e098dc3f677e7adbafda4dcdd4a461c", + "sha256:f3fd44cc362eee8ae569025f070d56208908916794b6ab21e139cea56470a2b3", + "sha256:f9944013588a3543fca795fffb0a070a31a243aa4f2d212f118aa95e69485831" ], "index": "pypi", - "version": "==1.23.3" + "version": "==0.29.32" + }, + "numpy": { + "hashes": [ + "sha256:01dd17cbb340bf0fc23981e52e1d18a9d4050792e8fb8363cecbf066a84b827d", + "sha256:06005a2ef6014e9956c09ba07654f9837d9e26696a0470e42beedadb78c11b07", + "sha256:09b7847f7e83ca37c6e627682f145856de331049013853f344f37b0c9690e3df", + "sha256:0aaee12d8883552fadfc41e96b4c82ee7d794949e2a7c3b3a7201e968c7ecab9", + "sha256:0cbe9848fad08baf71de1a39e12d1b6310f1d5b2d0ea4de051058e6e1076852d", + "sha256:1b1766d6f397c18153d40015ddfc79ddb715cabadc04d2d228d4e5a8bc4ded1a", + "sha256:33161613d2269025873025b33e879825ec7b1d831317e68f4f2f0f84ed14c719", + "sha256:5039f55555e1eab31124a5768898c9e22c25a65c1e0037f4d7c495a45778c9f2", + "sha256:522e26bbf6377e4d76403826ed689c295b0b238f46c28a7251ab94716da0b280", + "sha256:56e454c7833e94ec9769fa0f86e6ff8e42ee38ce0ce1fa4cbb747ea7e06d56aa", + "sha256:58f545efd1108e647604a1b5aa809591ccd2540f468a880bedb97247e72db387", + "sha256:5e05b1c973a9f858c74367553e236f287e749465f773328c8ef31abe18f691e1", + "sha256:7903ba8ab592b82014713c491f6c5d3a1cde5b4a3bf116404e08f5b52f6daf43", + "sha256:8969bfd28e85c81f3f94eb4a66bc2cf1dbdc5c18efc320af34bffc54d6b1e38f", + "sha256:92c8c1e89a1f5028a4c6d9e3ccbe311b6ba53694811269b992c0b224269e2398", + "sha256:9c88793f78fca17da0145455f0d7826bcb9f37da4764af27ac945488116efe63", + "sha256:a7ac231a08bb37f852849bbb387a20a57574a97cfc7b6cabb488a4fc8be176de", + "sha256:abdde9f795cf292fb9651ed48185503a2ff29be87770c3b8e2a14b0cd7aa16f8", + "sha256:af1da88f6bc3d2338ebbf0e22fe487821ea4d8e89053e25fa59d1d79786e7481", + "sha256:b2a9ab7c279c91974f756c84c365a669a887efa287365a8e2c418f8b3ba73fb0", + "sha256:bf837dc63ba5c06dc8797c398db1e223a466c7ece27a1f7b5232ba3466aafe3d", + "sha256:ca51fcfcc5f9354c45f400059e88bc09215fb71a48d3768fb80e357f3b457e1e", + "sha256:ce571367b6dfe60af04e04a1834ca2dc5f46004ac1cc756fb95319f64c095a96", + "sha256:d208a0f8729f3fb790ed18a003f3a57895b989b40ea4dce4717e9cf4af62c6bb", + "sha256:dbee87b469018961d1ad79b1a5d50c0ae850000b639bcb1b694e9981083243b6", + "sha256:e9f4c4e51567b616be64e05d517c79a8a22f3606499941d97bb76f2ca59f982d", + "sha256:f063b69b090c9d918f9df0a12116029e274daf0181df392839661c4c7ec9018a", + "sha256:f9a909a8bae284d46bbfdefbdd4a262ba19d3bc9921b1e76126b1d21c3c34135" + ], + "index": "pypi", + "version": "==1.23.5" }, "pandas": { "hashes": [ - "sha256:0d8d7433d19bfa33f11c92ad9997f15a902bda4f5ad3a4814a21d2e910894484", - "sha256:1642fc6138b4e45d57a12c1b464a01a6d868c0148996af23f72dde8d12486bbc", - "sha256:171cef540bfcec52257077816a4dbbac152acdb8236ba11d3196ae02bf0959d8", - "sha256:1b82ccc7b093e0a93f8dffd97a542646a3e026817140e2c01266aaef5fdde11b", - "sha256:1d34b1f43d9e3f4aea056ba251f6e9b143055ebe101ed04c847b41bb0bb4a989", - "sha256:207d63ac851e60ec57458814613ef4b3b6a5e9f0b33c57623ba2bf8126c311f8", - "sha256:2504c032f221ef9e4a289f5e46a42b76f5e087ecb67d62e342ccbba95a32a488", - "sha256:33a9d9e21ab2d91e2ab6e83598419ea6a664efd4c639606b299aae8097c1c94f", - "sha256:3ee61b881d2f64dd90c356eb4a4a4de75376586cd3c9341c6c0fcaae18d52977", - "sha256:41aec9f87455306496d4486df07c1b98c15569c714be2dd552a6124cd9fda88f", - "sha256:4e30a31039574d96f3d683df34ccb50bb435426ad65793e42a613786901f6761", - "sha256:5cc47f2ebaa20ef96ae72ee082f9e101b3dfbf74f0e62c7a12c0b075a683f03c", - "sha256:62e61003411382e20d7c2aec1ee8d7c86c8b9cf46290993dd8a0a3be44daeb38", - "sha256:73844e247a7b7dac2daa9df7339ecf1fcf1dfb8cbfd11e3ffe9819ae6c31c515", - "sha256:85a516a7f6723ca1528f03f7851fa8d0360d1d6121cf15128b290cf79b8a7f6a", - "sha256:86d87279ebc5bc20848b4ceb619073490037323f80f515e0ec891c80abad958a", - "sha256:8a4fc04838615bf0a8d3a03ed68197f358054f0df61f390bcc64fbe39e3d71ec", - "sha256:8e8e5edf97d8793f51d258c07c629bd49d271d536ce15d66ac00ceda5c150eb3", - "sha256:947ed9f896ee61adbe61829a7ae1ade493c5a28c66366ec1de85c0642009faac", - "sha256:a68a9b9754efff364b0c5ee5b0f18e15ca640c01afe605d12ba8b239ca304d6b", - "sha256:c76f1d104844c5360c21d2ef0e1a8b2ccf8b8ebb40788475e255b9462e32b2be", - "sha256:c7f38d91f21937fe2bec9449570d7bf36ad7136227ef43b321194ec249e2149d", - "sha256:de34636e2dc04e8ac2136a8d3c2051fd56ebe9fd6cd185581259330649e73ca9", - "sha256:e178ce2d7e3b934cf8d01dc2d48d04d67cb0abfaffdcc8aa6271fd5a436f39c8", - "sha256:e252a9e49b233ff96e2815c67c29702ac3a062098d80a170c506dff3470fd060", - "sha256:e9c5049333c5bebf993033f4bf807d163e30e8fada06e1da7fa9db86e2392009", - "sha256:fc987f7717e53d372f586323fff441263204128a1ead053c1b98d7288f836ac9" + "sha256:0183cb04a057cc38fde5244909fca9826d5d57c4a5b7390c0cc3fa7acd9fa883", + "sha256:1fc87eac0541a7d24648a001d553406f4256e744d92df1df8ebe41829a915028", + "sha256:220b98d15cee0b2cd839a6358bd1f273d0356bf964c1a1aeb32d47db0215488b", + "sha256:2552bffc808641c6eb471e55aa6899fa002ac94e4eebfa9ec058649122db5824", + "sha256:315e19a3e5c2ab47a67467fc0362cb36c7c60a93b6457f675d7d9615edad2ebe", + "sha256:344021ed3e639e017b452aa8f5f6bf38a8806f5852e217a7594417fb9bbfa00e", + "sha256:375262829c8c700c3e7cbb336810b94367b9c4889818bbd910d0ecb4e45dc261", + "sha256:457d8c3d42314ff47cc2d6c54f8fc0d23954b47977b2caed09cd9635cb75388b", + "sha256:4aed257c7484d01c9a194d9a94758b37d3d751849c05a0050c087a358c41ad1f", + "sha256:530948945e7b6c95e6fa7aa4be2be25764af53fba93fe76d912e35d1c9ee46f5", + "sha256:5ae7e989f12628f41e804847a8cc2943d362440132919a69429d4dea1f164da0", + "sha256:71f510b0efe1629bf2f7c0eadb1ff0b9cf611e87b73cd017e6b7d6adb40e2b3a", + "sha256:73f219fdc1777cf3c45fde7f0708732ec6950dfc598afc50588d0d285fddaefc", + "sha256:8092a368d3eb7116e270525329a3e5c15ae796ccdf7ccb17839a73b4f5084a39", + "sha256:82ae615826da838a8e5d4d630eb70c993ab8636f0eff13cb28aafc4291b632b5", + "sha256:9608000a5a45f663be6af5c70c3cbe634fa19243e720eb380c0d378666bc7702", + "sha256:a40dd1e9f22e01e66ed534d6a965eb99546b41d4d52dbdb66565608fde48203f", + "sha256:b4f5a82afa4f1ff482ab8ded2ae8a453a2cdfde2001567b3ca24a4c5c5ca0db3", + "sha256:c009a92e81ce836212ce7aa98b219db7961a8b95999b97af566b8dc8c33e9519", + "sha256:c218796d59d5abd8780170c937b812c9637e84c32f8271bbf9845970f8c1351f", + "sha256:cc3cd122bea268998b79adebbb8343b735a5511ec14efb70a39e7acbc11ccbdc", + "sha256:d0d8fd58df5d17ddb8c72a5075d87cd80d71b542571b5f78178fb067fa4e9c72", + "sha256:e18bc3764cbb5e118be139b3b611bc3fbc5d3be42a7e827d1096f46087b395eb", + "sha256:e2b83abd292194f350bb04e188f9379d36b8dfac24dd445d5c87575f3beaf789", + "sha256:e7469271497960b6a781eaa930cba8af400dd59b62ec9ca2f4d31a19f2f91090", + "sha256:e9dbacd22555c2d47f262ef96bb4e30880e5956169741400af8b306bbb24a273", + "sha256:f6257b314fc14958f8122779e5a1557517b0f8e500cfb2bd53fa1f75a8ad0af2" ], "index": "pypi", - "version": "==1.5.0" + "version": "==1.5.2" }, "python-dateutil": { "hashes": [ @@ -93,10 +139,10 @@ }, "pytz": { "hashes": [ - "sha256:220f481bdafa09c3955dfbdddb7b57780e9a94f5127e35456a48589b9e0c0197", - "sha256:cea221417204f2d1a2aa03ddae3e867921971d0d76f14d87abb4414415bbdcf5" + "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427", + "sha256:e89512406b793ca39f5971bc999cc538ce125c0e51c27941bef4568b460095e2" ], - "version": "==2022.2.1" + "version": "==2022.6" }, "six": { "hashes": [ diff --git a/makefile b/makefile new file mode 100644 index 0000000..5661ebc --- /dev/null +++ b/makefile @@ -0,0 +1,20 @@ +WORK=./yoshi_seals +PROCESS=$(WORK)/process +SHARED=$(WORK)/shared + +SETUP_CYTHON=setup_cython.py + +OBJS= $(PROCESS)/process.pyx $(SHARED)/array.pyx $(SETUP_CYTHON) + +PYTHON?=python +PARALLEL?=$(shell ${PYTHON} -c 'import sys; print("-j5" if sys.version_info >= (3,5) else "")' || true) + +all: $(OBJS) + python3 $(SETUP_CYTHON) build_ext --inplace $(PARALLEL) && \ + rm -r build + +clean: + + rm $(WORK)/**/*.cpython-310-x86_64-linux-gnu.so + rm $(WORK)/**/*.c + diff --git a/setup_cython.py b/setup_cython.py new file mode 100644 index 0000000..0a13927 --- /dev/null +++ b/setup_cython.py @@ -0,0 +1,29 @@ +import numpy +from Cython.Build import cythonize +from setuptools import Extension, setup + +ext_modules = [ + Extension( + "yoshi_seals.shared.array", + [ + "yoshi_seals/shared/array.pyx", + ], + extra_compile_args=["-O3", "-fopenmp"], + extra_link_args=['-fopenmp'], + define_macros=[("NPY_NO_DEPRECATED_API", "NPY_1_7_API_VERSION")], + ), + Extension( + "yoshi_seals.process.process", + [ + "yoshi_seals/process/process.pyx", + ], + extra_compile_args=["-O3", "-fopenmp"], + extra_link_args=['-fopenmp'], + define_macros=[("NPY_NO_DEPRECATED_API", "NPY_1_7_API_VERSION")] + ), +] + +setup( + ext_modules=cythonize(ext_modules), + include_dirs=[numpy.get_include()] +) diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/test_process.py b/test/test_process.py new file mode 100644 index 0000000..cdfc267 --- /dev/null +++ b/test/test_process.py @@ -0,0 +1,90 @@ +from yoshi_seals import process as ps + +import numpy as np + +from numpy import testing as npt +import unittest + + +class TestProcess(unittest.TestCase): + + def test_det(self): + a = np.array(([1., 0.], [0., 1.])) + + a_det = ps.det(a) + + self.assertEqual(a_det, 1) + + def test_inverse(self): + a = np.array(([1., 0.], [0., 1.])) + a_inv = ps.inverse(a) + + npt.assert_array_equal(a, a_inv) + + def test_hstack_returns_stacked_array(self): + a = np.array(([1., ], [1., ])) + b = np.array(([1., ], [1., ])) + + stacked = ps.hstack(a, b) + expected_stacked_array = np.array(([1., 1.], [1., 1.])) + + npt.assert_array_equal(stacked, expected_stacked_array) + + def test_hstack_throws_exception(self): + a = np.array(([1., ], [1., ])) + b = np.array(([1., ])) + + with self.assertRaises(ValueError): + ps.hstack(a, b) + + def test_vstack_returns_stacked_array(self): + a = np.array(([[1., 1.]])) + b = np.array(([[1., 1.]])) + + stacked = ps.vstack(a, b) + expected_stacked_array = np.array(([1., 1.], [1., 1.])) + + npt.assert_array_equal(stacked, expected_stacked_array) + + def test_vstack_throws_exception(self): + a = np.array(([[1., 1.]])) + b = np.array(([[1.]])) + + with self.assertRaises(ValueError): + ps.vstack(a, b) + + def test_gauss(self): + a = np.array(([4., 3.], [3., 2.])) + b = np.array(([1.], [1.])) + + matrix = ps.gauss(a, b) + expected_matrix = np.array([[1.], [-1.]]) + + npt.assert_array_equal(matrix, expected_matrix) + + def test_cholesky(self): + a = np.array(([4., 10., 8.], [10., 26., 26], [8., 26., 61.])) + b = np.array(([44.], [128.], [214.])) + + matrix = ps.cholesky(a, b) + expected_matrix = np.array([[-8.], [6.], [2.]]) + + npt.assert_almost_equal(matrix, expected_matrix) + + def test_decomposition(self): + a = np.array(([4., 3.], [3., 2.])) + b = np.array(([1.], [1.])) + + matrix = ps.decomposition(a, b) + expected_matrix = np.array([[1.], [-1.]]) + + npt.assert_array_equal(matrix, expected_matrix) + + def test_cramer(self): + a = np.array(([4., 3.], [3., 2.])) + b = np.array(([1.], [1.])) + + matrix = ps.cramer(a, b) + expected_matrix = np.array([[1.], [-1.]]) + + npt.assert_array_equal(matrix, expected_matrix) diff --git a/yoshi-seals/process/__init__.py b/yoshi-seals/process/__init__.py deleted file mode 100644 index 985e6e0..0000000 --- a/yoshi-seals/process/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -# Seals - Program made for educational intent, can be freely distributed -# and can be used for economical intent. I will not take legal actions -# unless my intelectual propperty, the code, is stolen or change without permission. - -# Copyright (C) 2020 VItor Hideyoshi Nakazone Batista - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as published by -# the Free Software Foundation. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -from .process import identity -from .process import gauss -from .process import inverse -from .process import cholesky -from .process import decomposition -from .process import cramer \ No newline at end of file diff --git a/yoshi-seals/process/process.py b/yoshi-seals/process/process.py deleted file mode 100644 index 3ba8864..0000000 --- a/yoshi-seals/process/process.py +++ /dev/null @@ -1,239 +0,0 @@ -# Seals - Program made for educational intent, can be freely distributed -# and can be used for economical intent. I will not take legal actions -# unless my intelectual propperty, the code, is stolen or change without permission. - -# Copyright (C) 2020 VItor Hideyoshi Nakazone Batista - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as published by -# the Free Software Foundation. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -import numpy as np -import math - -def identity(matrix: np.ndarray) -> np.ndarray: - - i = 0 - - while (i < matrix.shape[0]): - - j = 0 - - while (j < matrix.shape[0]): - - if (i == j): - - matrix[i][j] = 1 - - elif (i != j): - - matrix[i][j] = 0 - - j += 1 - - i += 1 - - return matrix - -def gauss(a: np.ndarray) -> np.ndarray: - - for i in range(a.shape[0]): - - k = i + 1 - - while (k np.ndarray: - - matrix = np.hstack(matrix,np.identity(matrix.shape[0])) - i = 0 - k = 0 - - while (i < matrix.shape[0]): - - if (matrix[i][i] == 0): - - n = i - - while (matrix[i][i] == 0) and (n < matrix.shape[0]): - - temp = matrix[i].copy() - matrix[i] = matrix[n] - matrix[n] = temp - - n += 1 - - while (k < matrix.shape[0]): - - if (k == i) or (matrix[k][i] == 0) or (matrix[i][i] == 0): - - k += 1 - - else: - - mult = matrix[k][i]/matrix[i][i] - matrix[k] = matrix[k] - mult*matrix[i] - k += 1 - - i += 1 - k = 0 - - i = 0 - - while ((i) < matrix.shape[0]) and (matrix[i][i] != 0): - - matrix[i] = matrix[i]/matrix[i][i] - i += 1 - - return matrix[:,(matrix.shape[0]):] - -def cholesky(A: np.ndarray, b: np.ndarray) -> np.ndarray: - - g = np.zeros((A.shape)) - - i = 0 - j = 0 - - while j < A.shape[1]: - while i < A.shape[0]: - - if i == 0 and j == 0: - - g[i][j] = math.sqrt(A[0][0]) - - elif j == 0: - - g[i][j] = A[i][0]/g[0][0] - - elif i == j: - - k = 0 - theta = 0 - - while k < i: - - theta += g[i][k]**2 - k += 1 - - g[i][j] = math.sqrt(A[i][i] - theta) - - else: - - k = 0 - theta = 0 - - while k < j: - - theta += g[i][k]*g[j][k] - k += 1 - - g[i][j] = (A[i][j] - theta)/g[j][j] - - i += 1 - - j += 1 - i = j - - y = (inverse(g)).dot(b) - - x = (inverse(g.T)).dot(y) - - return x - -def decomposition(U: np.ndarray, b: np.ndarray) -> np.ndarray: - - L = identity(np.zeros(U.shape)) - - i = 0 - k = 0 - - while (i < U.shape[0]): - - k = 0 - - if (U[i][i] == 0): - - n = i - - while (U[i][i] == 0) and (n < U.shape[0]): - - temp = U[i].copy() - U[i] = U[n] - U[n] = temp - - n += 1 - - while (k < U.shape[0]): - - if (k <= i) or (U[i][i] == 0): - - k += 1 - - else: - L[k][i] = U[k][i]/U[i][i] - U[k] = U[k] - L[k][i]*U[i] - k += 1 - - i += 1 - - y = (inverse(L)).dot(b) - - x = (inverse(U)).dot(y) - - return x - -def cramer(A: np.ndarray, b: np.ndarray) -> np.ndarray: - - x = np.vstack(np.zeros(b.shape)) - k = 0 - - while (k < A.shape[0]): - - temp = A.copy() - temp[:,k] = b - - x[k] = np.linalg.det(temp)/np.linalg.det(A) - - k += 1 - - return x \ No newline at end of file diff --git a/yoshi_seals/__init__.pxd b/yoshi_seals/__init__.pxd new file mode 100644 index 0000000..e69de29 diff --git a/yoshi-seals/__init__.py b/yoshi_seals/__init__.py similarity index 100% rename from yoshi-seals/__init__.py rename to yoshi_seals/__init__.py diff --git a/yoshi-seals/eigen/__init__.py b/yoshi_seals/eigen/__init__.py similarity index 100% rename from yoshi-seals/eigen/__init__.py rename to yoshi_seals/eigen/__init__.py diff --git a/yoshi-seals/eigen/eigen.py b/yoshi_seals/eigen/eigen.py similarity index 100% rename from yoshi-seals/eigen/eigen.py rename to yoshi_seals/eigen/eigen.py diff --git a/yoshi-seals/insert/__init__.py b/yoshi_seals/insert/__init__.py similarity index 100% rename from yoshi-seals/insert/__init__.py rename to yoshi_seals/insert/__init__.py diff --git a/yoshi-seals/insert/insert.py b/yoshi_seals/insert/insert.py similarity index 100% rename from yoshi-seals/insert/insert.py rename to yoshi_seals/insert/insert.py diff --git a/yoshi_seals/process/__init__.py b/yoshi_seals/process/__init__.py new file mode 100644 index 0000000..bbbbd1a --- /dev/null +++ b/yoshi_seals/process/__init__.py @@ -0,0 +1,35 @@ +import yoshi_seals.process.process as ps + +import numpy as np + + +def det(a: np.ndarray) -> float: + return ps.det(a) + + +def inverse(a: np.ndarray) -> np.ndarray: + return ps.inverse(a) + + +def hstack(a: np.ndarray, b: np.ndarray) -> np.ndarray: + return ps.hstack(a, b) + + +def vstack(a: np.ndarray, b: np.ndarray) -> np.ndarray: + return ps.vstack(a, b) + + +def gauss(a: np.ndarray, b: np.ndarray) -> np.ndarray: + return ps.gauss(a, b) + + +def cholesky(a: np.ndarray, b: np.ndarray) -> np.ndarray: + return ps.cholesky(a, b) + + +def decomposition(a: np.ndarray, b: np.ndarray) -> np.ndarray: + return ps.decomposition(a, b) + + +def cramer(a: np.ndarray, b: np.ndarray) -> np.ndarray: + return ps.cramer(a, b) diff --git a/yoshi_seals/process/process.pyx b/yoshi_seals/process/process.pyx new file mode 100644 index 0000000..99a4fec --- /dev/null +++ b/yoshi_seals/process/process.pyx @@ -0,0 +1,193 @@ +# Seals - Program made for educational intent, can be freely distributed +# and can be used for economical intent. I will not take legal actions +# unless my intelectual propperty, the code, is stolen or change without permission. + +# Copyright (C) 2020 VItor Hideyoshi Nakazone Batista + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as published by +# the Free Software Foundation. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +from yoshi_seals.shared cimport array + +from libc.stdlib cimport malloc +from libc cimport math + +cimport numpy as np +import numpy as np + +cpdef double det(double[::,::] a): + return array.det(a) + +cpdef np.ndarray[np.float64_t, ndim=2] inverse(double[::,::] matrix): + return np.asarray(array.inverse(matrix)) + +cpdef np.ndarray[np.float64_t, ndim=2] hstack(double[::,::] a, double[::,::] b): + return np.asarray(array.hstack(a, b)) + +cpdef np.ndarray[np.float64_t, ndim=2] vstack(double[::,::] a, double[::,::] b): + return np.asarray(array.vstack(a, b)) + +cpdef np.ndarray[np.float64_t, ndim=2] gauss(double[::,::] A, double[::,::] b): + + cdef: + int i = 0, j = 0, k = 0, l = 0, reversed_index = 0 + + double[:] tmp + double sum_var + + double[::,::] a = array.hstack(A,b) + + double *c_pointer = malloc(A.shape[1]*sizeof(double)) + double[:] x = c_pointer + + if not c_pointer: + raise MemoryError() + + for i in range(A.shape[0]): + + l = 1 + while i < A.shape[1] and a[i][i] == 0 and (l + i) < A.shape[0]: + + tmp = a[i] + a[i] = a[i+l] + a[i+l] = tmp + + l += 1 + + for k in range(i + 1, A.shape[1]): + + if a[k][i] != 0: + a[k] = array.subtract(a[k],array.mult(a[i], (a[k][i]/a[i][i]))) + + for j in range(A.shape[1]): + + sum_var = 0 + reversed_index = (A.shape[1] - 1) - j + + for k in range(reversed_index,A.shape[1]): + sum_var += a[reversed_index][k]*x[k] + x[reversed_index] = (a[reversed_index][A.shape[1]] - sum_var)/a[reversed_index][reversed_index] + + return np.asarray(x).reshape(b.shape[0],b.shape[1]) + +cpdef np.ndarray[np.float64_t, ndim=2] cholesky(double[:,:] A, double[:,:] b): + + cdef: + int i = 0, j = 0, size_x = A.shape[0], size_y = A.shape[1] + + double *c_pointer = malloc(size_x*size_y*sizeof(double)) + double[::,::] g = c_pointer, y, x + + while j < size_y: + while i < size_x: + if i == 0 and j == 0: + g[i][j] = math.sqrt(A[0][0]) + + elif j == 0: + g[i][j] = A[i][0] / g[0][0] + + elif i == j: + k = 0 + theta = 0 + + while k < i: + theta += g[i][k] ** 2 + k += 1 + + g[i][j] = math.sqrt(A[i][i] - theta) + + else: + k = 0 + theta = 0 + + while k < j: + theta += g[i][k] * g[j][k] + k += 1 + + g[i][j] = (A[i][j] - theta) / g[j][j] + + i += 1 + + j += 1 + i = j + + y = array.dot(array.inverse(g), b) + + x = array.dot(array.inverse(array.transpose(g)), y) + + return np.asarray(x) + + +cpdef np.ndarray[np.float64_t, ndim=2] decomposition(double[::,::] U, double[::,::] b): + + cdef: + int i = 0, k = 0 + + double[::,::] L = array.identity(U.shape[0]), y, x + + for i in range(U.shape[0]): + + if U[i][i] == 0: + + n = i + + while (U[i][i] == 0) and (n < U.shape[0]): + temp = U[i].copy() + U[i] = U[n] + U[n] = temp + + n += 1 + + for k in range(U.shape[0]): + + if (k > i) and (U[i][i] != 0): + + L[k][i] = U[k][i] / U[i][i] + U[k] = array.subtract(U[k], array.mult(U[i], L[k][i])) + + y = array.dot(array.inverse(L), b) + + x = array.dot(array.inverse(U), y) + + return np.asarray(x) + +cpdef np.ndarray[np.float64_t, ndim=2] cramer(double[:,:] A, double[:,:] b): + + cdef: + int size_a_y = A.shape[0], size_a_x = A.shape[1] + int size_b_y = b.shape[0], size_b_x = b.shape[1] + + int k = 0 + + double *c_pointer_tmp = malloc(size_a_x*size_a_y*sizeof(double)) + double[::,::] tmp = c_pointer_tmp + + double *c_pointer_x = malloc(size_b_x*size_b_y*sizeof(double)) + double[::,::] x = c_pointer_x + + if size_a_y != size_b_y: + raise ValueError("The matrices must have the same height.") + if size_b_x != 1: + raise ValueError("The b matrix must be a column matrix.") + + for k in range(size_a_x): + tmp = A.copy() + + for i in range(size_a_y): + tmp[i, k] = b[i,0] + + x[k,0] = np.linalg.det(tmp) / np.linalg.det(A) + + k += 1 + + return np.asarray(x) \ No newline at end of file diff --git a/yoshi-seals/scan/__init__.py b/yoshi_seals/scan/__init__.py similarity index 100% rename from yoshi-seals/scan/__init__.py rename to yoshi_seals/scan/__init__.py diff --git a/yoshi-seals/scan/scan.py b/yoshi_seals/scan/scan.py similarity index 100% rename from yoshi-seals/scan/scan.py rename to yoshi_seals/scan/scan.py diff --git a/yoshi_seals/shared/__init__.pxd b/yoshi_seals/shared/__init__.pxd new file mode 100644 index 0000000..e69de29 diff --git a/yoshi_seals/shared/__init__.py b/yoshi_seals/shared/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/yoshi_seals/shared/array.pxd b/yoshi_seals/shared/array.pxd new file mode 100644 index 0000000..831f6ba --- /dev/null +++ b/yoshi_seals/shared/array.pxd @@ -0,0 +1,25 @@ +cdef double[::] mult(double[::] array, double value) + +cdef double[::] div(double[::] array, double value) + +cdef double[::] addition(double[::] a, double[::] b) + +cdef double[::] subtract(double[::] a, double[::] b) + +cdef double[::,:] hstack(double[:,:] a, double[:,:] b) + +cdef double[::,::] vstack(double[:,:] a, double[:,:] b) + +cdef double[::,::] identity(int size) + +cdef double[:,:] zeros((int, int) sizes) + +cdef double[:,:] ones((int, int) sizes) + +cdef double[:,:] inverse(double[:,:] a) + +cdef double[:,:] transpose(double[:,:] a) + +cdef double[:,:] dot(double[:,:] a, double[:,:] b) + +cdef double det(double[::,::] a) \ No newline at end of file diff --git a/yoshi_seals/shared/array.pyx b/yoshi_seals/shared/array.pyx new file mode 100644 index 0000000..3aab424 --- /dev/null +++ b/yoshi_seals/shared/array.pyx @@ -0,0 +1,251 @@ +from libc.stdlib cimport malloc + +cimport numpy as np +import numpy as np + + +cdef double[::] mult(double[::] array, double value): + + cdef int size = array.shape[0], i = 0 + + cdef: + double *c_pointer = malloc(size*sizeof(double)) + double[::] mult_array = c_pointer + + for i in range(size): + + mult_array[i] = array[i]*value + + return mult_array + +cdef double[::] div(double[::] array, double value): + + cdef int size = array.shape[0], i = 0 + + cdef: + double *c_pointer = malloc(size*sizeof(double)) + double[::] mult_array = c_pointer + + for i in range(size): + + mult_array[i] = array[i]/value + + return mult_array + +cdef double[::] addition(double[::] a, double[::] b): + + cdef int size_a = a.shape[0], size_b = b.shape[0], i = 0 + cdef double *c_pointer = malloc(size_a*sizeof(double)) + cdef double[::] mult_array = c_pointer + + for i in range(size_a): + + mult_array[i] = a[i] + b[i] + + return mult_array + +cdef double[::] subtract(double[::] a, double[::] b): + + cdef int size_a = a.shape[0], size_b = b.shape[0], i = 0 + cdef double *c_pointer = malloc(size_a*sizeof(double)) + cdef double[::] mult_array = c_pointer + + for i in range(size_a): + + mult_array[i] = a[i] - b[i] + + return mult_array + +cdef double[::,::] identity(int size): + + cdef int i = 0 + + cdef double *c_pointer = malloc(size*size*sizeof(double)) + cdef double[::,:] matrix = c_pointer + + for i in range(size): + for j in range(size): + if i == j: + matrix[i][j] = 1 + + elif i != j: + matrix[i][j] = 0 + + return matrix + +cdef double[:,:] zeros((int, int) size): + + cdef int i = 0, j = 0 + + cdef: + + double *c_pointer = malloc(size[0]*size[1]*sizeof(double)) + double[:,:] id_array = c_pointer + + if not c_pointer: + raise MemoryError() + + for i in range(size[0]): + for j in range(size[1]): + id_array[i,j] = 0.0 + + return id_array + +cdef double[:,:] ones((int, int) size): + + cdef int i = 0, j = 0 + + cdef: + + double *c_pointer = malloc(size[0]*size[1]*sizeof(double)) + double[:,:] id_array = c_pointer + + for i in range(size[0]): + for j in range(size[1]): + id_array[i,j] = 1.0 + + return id_array + +cdef double[:,:] hstack(double[:,:] a, double[:,:] b): + + cdef: + + int i, j + int a_x = a.shape[0], a_y = a.shape[1] + int b_x = b.shape[0], b_y = b.shape[1] + int size_x = a_x, size_y = a_y + b_y + + double *c_pointer = malloc(size_x*size_y*sizeof(double)) + double[::,::] matrix = c_pointer + + if a_x != b_x: + raise ValueError("Cannot hstack matrices") + + for i in range(size_x): + for j in range(size_y): + if j < a_y: + matrix[i,j] = a[i,j] + else: + matrix[i,j] = b[i,j-a_y] + + return matrix + +cdef double[:,:] vstack(double[:,:] a, double[:,:] b): + + cdef: + + int i, j + int a_x = a.shape[0], b_x = b.shape[0] + int a_y = a.shape[1], b_y = b.shape[1] + int size_x = a_x + b_x, size_y = a_y + + double *c_pointer = malloc(size_x*size_y*sizeof(double)) + double[:,:] matrix = c_pointer + + if a_y != b_y: + raise ValueError("Cannot vstack matrices") + + for i in range(size_x): + for j in range(size_y,): + if i < a_x: + matrix[i,j] = a[i,j] + else: + matrix[i,j] = b[i-a_x, j] + + return matrix + +cdef double[:,:] inverse(double[:,:] a): + + cdef: + + int i = 0, k = 0, n, size = a.shape[0] + + double[:,:] matrix = hstack(a,identity(size)) + double mult_const + double[:] tmp + + if a.shape[0] != a.shape[1]: + raise ValueError("Non Quadratic Matrix doesn't have an Inverse Matrix") + + for i in range(size): + + if matrix[i][i] == 0: + + n = i + + while (matrix[i][i] == 0) and (n < size): + + tmp = matrix[i] + matrix[i] = matrix[n].copy() + matrix[n] = tmp + + n += 1 + + for k in range(size): + + if (k != i) and (matrix[i][i] != 0): + + mult_const = matrix[k][i]/matrix[i][i] + matrix[k] = subtract(matrix[k], mult(matrix[i], mult_const)) + + for k in range(size): + if matrix[k][k] != 0: + matrix[k] = div(matrix[k], matrix[k][k]) + + return matrix[:,size:] + +cdef double[:,:] transpose(double[:,:] a): + + cdef: + + int size_x = a.shape[0], size_y = a.shape[1] + + double *c_pointer = malloc(size_y*size_x*sizeof(double)) + double[:,:] tmp = c_pointer + + for i in range(size_x): + for j in range(size_y): + tmp[j,i] = a[i,j] + + return tmp + +cdef double[:,:] dot(double[:,:] a, double[:,:] b): + c = np.zeros((a.shape[0], b.shape[1])) + + for i in range(a.shape[0]): + for j in range(b.shape[1]): + for k in range(a.shape[0]): + c[i][j] += a[i][k] * b[k][j] + + return c + +cdef double det(double[::,::] a): + + cdef: + + double[:,:] tmp + double total = 0, sub_det + + int size_x = a.shape[0], size_y = a.shape[1], i + + if size_x != size_y: + raise ValueError("Determinant Operation is only valid for Quadratic Matrices.") + + if size_x == 2 and size_y == 2: + total = a[0][0] * a[1][1] - a[1][0] * a[0][1] + return total + + for i in range(size_x): + + tmp = a.copy() + tmp = tmp[1:] + + for i in range(size_y): + tmp[i] = addition(tmp[i][0:i], tmp[i][i + 1:]) + + sign = (-1) ** (i % 2) + sub_det = det(tmp) + + total += sign * a[0][i] * sub_det + + return total \ No newline at end of file diff --git a/yoshi-seals/write/__init__.py b/yoshi_seals/write/__init__.py similarity index 100% rename from yoshi-seals/write/__init__.py rename to yoshi_seals/write/__init__.py diff --git a/yoshi-seals/write/write.py b/yoshi_seals/write/write.py similarity index 100% rename from yoshi-seals/write/write.py rename to yoshi_seals/write/write.py