{"id":24865513,"url":"https://github.com/melsman/moa","last_synced_at":"2026-02-12T10:04:28.268Z","repository":{"id":148050725,"uuid":"5449305","full_name":"melsman/MoA","owner":"melsman","description":"Multi-dimentional array calculus in Standard ML","archived":false,"fork":false,"pushed_at":"2021-01-19T23:22:03.000Z","size":218,"stargazers_count":8,"open_issues_count":0,"forks_count":1,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-26T18:54:58.571Z","etag":null,"topics":["apl","multi-dimensional-arrays","smlpkg"],"latest_commit_sha":null,"homepage":"","language":"Standard ML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/melsman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2012-08-17T07:36:12.000Z","updated_at":"2021-01-19T23:18:35.000Z","dependencies_parsed_at":null,"dependency_job_id":"a9721d52-d349-4094-ab36-6c785c089b65","html_url":"https://github.com/melsman/MoA","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/melsman/MoA","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/melsman%2FMoA","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/melsman%2FMoA/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/melsman%2FMoA/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/melsman%2FMoA/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/melsman","download_url":"https://codeload.github.com/melsman/MoA/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/melsman%2FMoA/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270976624,"owners_count":24678529,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-18T02:00:08.743Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apl","multi-dimensional-arrays","smlpkg"],"created_at":"2025-01-31T23:59:59.511Z","updated_at":"2026-02-12T10:04:23.249Z","avatar_url":"https://github.com/melsman.png","language":"Standard ML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MoA [![CI](https://github.com/melsman/MoA/workflows/CI/badge.svg)](https://github.com/melsman/MoA/actions)\n\nStandard ML library for Vectors and Multi-dimensional Arrays.\n\n## Overview of MLB files\n\n* `lib/github.com/melsman/MoA/vec/vec.mlb`:\n\n  Implementation of one-dimensional vectors. Several implementations\n  are included, including a version based on pull and push arrays.\n\n  - **signature** [`VEC`](lib/github.com/melsman/MoA/vec/vec.sig)\n  - **structure** `ListVec : VEC`\n  - **structure** `Fvec : VEC`\n  - **structure** `PPvec : VEC`\n\n* `lib/github.com/melsman/MoA/ilvec/il.mlb`:\n\n  Implementation of code-generational one-dimensional pull arrays of\n  type `INT * (INT -\u003e Exp)`.\n\n  - **signature** [`ILVEC`](lib/github.com/melsman/MoA/ilvec/ilvec.sig)\n  - **structure** `Type : Type`\n  - **structure** `Exp : EXP`\n  - **structure** `Program : PROGRAM`\n\n\n* `lib/github.com/melsman/MoA/ilvec/il2m.mlb`:\n\n  Implementation of code-generational one-dimensional pull arrays of\n  type `INT * (INT -\u003e Exp M)`. Support for nested operations on\n  vectors.\n\n* `lib/github.com/melsman/MoA/moa.mlb`:\n\n  Implementation of multi-dimensional array calculus. Makes use of\n  `vec.mlb`.\n\n* `lib/github.com/melsman/MoA/ilmoa.mlb`:\n\n  Implementation of code-generational multi-dimensional array\n  calculus. Makes use of `ilvec/il.mlb`.\n\n* `lib/github.com/melsman/MoA/ilapl.mlb`:\n\n  Implementation of code-generational multi-dimensional array calculus\n  with APL semantics. Makes use of `il2m.mlb`.\n\nThe \"il\" versions of the vector and array libraries are\nimplementations that generate residual intermediate language \"C like\"\ncode from the specification of the vector or array program. Contrary,\nthe non-\"il\" versions of the libraries are implementations for which\nthe vector and array operations are performed in ML itself.\n\n## Use of the package\n\nThis library is set up to work well with the SML package manager\n[smlpkg](https://github.com/diku-dk/smlpkg).  To use the package, in\nthe root of your project directory, execute the command:\n\n```\n$ smlpkg add github.com/melsman/MoA\n```\n\nThis command will add a _requirement_ (a line) to the `sml.pkg` file in your\nproject directory (and create the file, if there is no file `sml.pkg`\nalready).\n\nTo download the library into the directory\n`lib/github.com/melsman/MoA`, execute the command:\n\n```\n$ smlpkg sync\n```\n\nYou can now reference the `mlb`-file using relative paths from within\nyour project's `mlb`-files.\n\nNotice that you can choose either to treat the downloaded package as\npart of your own project sources (vendoring) or you can add the\n`sml.pkg` file to your project sources and make the `smlpkg sync`\ncommand part of your build process.\n\n## One-dimensional vector implementations\n\nThe sources contain various basic vector library implementations that\nare used as the basis for the MoA realization. The `vec/` folder\ncontains three implementations of the `VEC` signature:\n\n  1. A reference vector implementation based on Standard ML lists.\n\n  1. An implementation based on _pull arrays_, which consists of a\n     number denoting the size of the array and a function for reading\n     an element of the array, given an index. Pull arrays support map\n     fusion and work well up-to a number of extensions, including drop\n     and take functionality.\n\n  1. An implementation based on both pull arrays and _push arrays_,\n     which are continuation-based representations of arrays and dual to\n     pull arrays in the sense that they support concatenation well,\n     but drop and take operations not so well.\n\nThe `ilvec/` folder contains different vector libraries that\nsupport map fusion and generate residual (C-like) code. The\n`il2.mlb` implementation supports nesting of vectors and thus,\nnested folds. As an example, let's first construct a matrix containing\nthe small multiplification table:\n\n```sml\nval mat = tabulate (I 10) (fn i =\u003e tabulate (I 10) (fn j =\u003e i * j))\n```\n\nHere the `I` function lifts integers into the vector expression\nlanguage, on which all calculations are performed. The lifting allows\noperations on vector expressions to be residualized into the C-like\ntarget language. Now, let's write some code for summing up all the\nvalues in the table:\n\n```sml\nval m = foldr (fn (r, a) =\u003e foldr (ret o op +) a r) (I 0) mat\n```\n\nHere we see two nested folds, with the outer foldr folding over the\nrows of the matrix with `I 0` as the base value for the\naccumulator. The inner foldr adds all elements in a row to the outer\naccumulator.\n\nHere are the types of `foldr` and `tabulate`:\n\n```sml\nval foldr    : ('a t * 'b t -\u003e 'b t M) -\u003e 'b t -\u003e 'a v -\u003e 'b t M\nval tabulate : INT -\u003e (INT -\u003e 'a t) -\u003e 'a v\n```\n\nWe see that `foldr` returns a monadic value, which we can \"run\" using\nthe `runM` function, which again generates a residual program\n(slightly simplified):\n\n```c\nint n49 = 0;\nfor (int n52 = 0; n52 \u003c 10; n52++) {\n    int n53 = n49;\n    for (int n55 = 0; n55 \u003c 10; n55++) {\n        n53 += ((9-n52)*(9-n55));\n    }\n    n49 = n53;\n}\n```\n\nAfter executing the above code, the result is present in variable\n`n49`.\n\nThe `il2m.mlb` implementation further extends the simpler solution with\nan implementation of pull-arrays that maps indexes to expression\nmonads, so as to support simple implementations of\nmatrix-multiplication and nested reductions along different axes of a\nmulti-dimensional array.\n\n## MoA - Multi-dimensional arrays\n\nThe `moa.mlb` and `ilmoa.mlb` libraries provide implementations of\na multi-dimentional array calculus based on the paper:\n\n * __G. Hains et L. M. R. Mullin__. _An algebra of multidimensional\n   arrays_. Publication 783, DIRO, Departement d'Informatique et de\n   Recherche Operationnelle, Universite de Montreal, 1991.\n\nIn essence, arrays are implemented as a product of two one-dimensional\nvectors, where the first vector specifies the shape of the array\n(ranks and dimensions) and where the second vector specifies the\ncontent of the array, as contiguous elements.\n\nWe demonstrate the `ilmoa.mlb` library by example. Consider the\nfollowing signal processing program:\n\n```sml\nfun diff (signal (*:n*)) (*:n-1*) =\n    rrotate (I 1) signal \u003e\u003e= (fn r =\u003e\n      sum Double (op -) signal r \u003e\u003e= (fn (r' (*:n*)) =\u003e\n      ret (drop (I 1) r')))\nfun maxsv s v = mmap (fn x =\u003e max x s) v   (* scalar-vector max *)\nfun minsv s v = mmap (fn x =\u003e min x s) v   (* scalar-vector min *)\nfun prodsv s v = mmap (fn x =\u003e x * s) v    (* scalar-vector multiplication *)\nfun addsv s v = mmap (fn x =\u003e x + s) v     (* scalar-vector addition *)\nfun divv v1 v2 = sum Double (op /) v1 v2   (* element-wise vector division *)\nfun signal (SIG (*:n*)) =\n    catenate (scl (D 0.0)) SIG \u003e\u003e= (fn (c (*:n+1*)) =\u003e\n    diff c \u003e\u003e= (fn (v (*:n*)) =\u003e\n    divv v (addsv (D 0.01) SIG) \u003e\u003e= (fn tmp =\u003e\n    ret(maxsv (D ~50.0) (minsv (D 50.0) (prodsv (D 50.0) tmp))))))\n```\n\nIn APL, the code is written\n\n```apl\ndiff ← {1↓⍵−¯1⌽⍵}\nsignal ← {¯50⌈50⌊50×(diff 0,⍵)÷0.01+⍵}\n```\n\nHere is the driver code for the program:\n\n```sml\n  val program =\n    let val n = I 500\n        val v = iota (I 2 * n)\n        infix %\n        val v = mmap (fn x =\u003e x % (I 200)) v\n        val v = mmap i2d v\n        val v = mmap (fn d =\u003e d / D 2.0) v\n    in mem v \u003e\u003e= (fn v =\u003e\n       signal v \u003e\u003e= (fn v' =\u003e\n       red (ret o op +) (D 0.0) v'))\n    end\n```\n\nThe driver code first constructs an array of 1000 elements, processes\nthe elements of the array (by calling the `signal` function), and\nfinally, sums up the resulting array.\n\nHere is the residual program generated (slightly modified):\n\n```c\ndouble kernel() {\n  double[] n468 = alloc(1000*sizeof(double));\n  for (int n478 = 0; n478 \u003c 1000; n478++) {\n    n468[n478] = (i2d((1+n478)%200)/2.0);\n  }\n  double n471 = 0.0;\n  for (int n479 = 0; n479 \u003c 1000; n479++) {\n    n471 = (max(min((((((n479\u003c1) ? 0.0 : n468[(-1+n479)])-n468[n479])/(n468[n479]+0.01))*50.0),50.0),-50.0)+n471);\n  }\n  return n471;\n}\n```\n\nThe first part of the generated program constructs a 1000-element\narray of doubles. The second part of the generated program processes\neach element of the array and sums up the results.\n\nAlthough we can rely on the target language compiler to do a good job\nof generating efficient code, we may want to perform certain\noptimizations during target code generation. For instance, in the\nexample above, we could recognize the opportunity to roll out the\nsecond for-loop one time, which will eliminate the continued test on\nvariable `n479`.\n\n## More to come\n\nThe goal of this project is to cover a large set of APL array\ncombinators. Composed with a parsing solution for APL, one can\nenvision a compilation scheme for parsing a subset of APL into the MoA\ncombinators, which again will generate low-level C-like kernels\n(appropriate for GPGPUs, etc.)\n\n## Related work\n\nThere are lots of related work involving implementation of array languages.\n\n * Nick Nickolov. [Open source APL interpreter in Javascript](http://ngn.github.com/apl/web/index.html). [Github project](https://github.com/ngn/apl).\n\n * Roy E. Lowrance. [APL Literature Review](http://www.cs.nyu.edu/manycores/litrev.pdf). February 22, 2009.\n\n * Timothy A. Budd. [A New Approach to Vector Code Generation for Applicative Languages](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.52.3959). September 20, 1994.\n\n## LICENSE\n\nThis software is published under the [MIT License](MIT_LICENSE.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmelsman%2Fmoa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmelsman%2Fmoa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmelsman%2Fmoa/lists"}