├── .github
└── workflows
│ ├── doc-build.yml
│ ├── release.yml
│ ├── snapshot.yml
│ └── test.yml
├── .gitignore
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── epl.html
├── pom.xml
└── src
├── main
└── clojure
│ └── clojure
│ └── algo
│ ├── generic.clj
│ └── generic
│ ├── arithmetic.clj
│ ├── collection.clj
│ ├── comparison.clj
│ ├── functor.clj
│ └── math_functions.clj
└── test
└── clojure
└── clojure
└── algo
└── generic
├── test_collection.clj
├── test_comparison.clj
├── test_complex.clj
└── test_functor.clj
/.github/workflows/doc-build.yml:
--------------------------------------------------------------------------------
1 | name: Build API Docs
2 |
3 | on:
4 | workflow_dispatch:
5 |
6 | jobs:
7 | call-doc-build-workflow:
8 | uses: clojure/build.ci/.github/workflows/doc-build.yml@master
9 | with:
10 | project: clojure/algo.generic
11 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release on demand
2 |
3 | on:
4 | workflow_dispatch:
5 | inputs:
6 | releaseVersion:
7 | description: "Version to release"
8 | required: true
9 | snapshotVersion:
10 | description: "Snapshot version after release"
11 | required: true
12 |
13 | jobs:
14 | call-release:
15 | uses: clojure/build.ci/.github/workflows/release.yml@master
16 | with:
17 | releaseVersion: ${{ github.event.inputs.releaseVersion }}
18 | snapshotVersion: ${{ github.event.inputs.snapshotVersion }}
19 | secrets: inherit
--------------------------------------------------------------------------------
/.github/workflows/snapshot.yml:
--------------------------------------------------------------------------------
1 | name: Snapshot on demand
2 |
3 | on: [workflow_dispatch]
4 |
5 | jobs:
6 | call-snapshot:
7 | uses: clojure/build.ci/.github/workflows/snapshot.yml@master
8 | secrets: inherit
9 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Test
2 |
3 | on: [push]
4 |
5 | jobs:
6 | call-test:
7 | uses: clojure/build.ci/.github/workflows/test.yml@master
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | This is a [Clojure contrib] project.
2 |
3 | Under the Clojure contrib [guidelines], this project cannot accept
4 | pull requests. All patches must be submitted via [JIRA].
5 |
6 | See [Contributing] on the Clojure website for
7 | more information on how to contribute.
8 |
9 | [Clojure contrib]: https://clojure.org/community/contrib_libs
10 | [Contributing]: https://clojure.org/community/contributing
11 | [JIRA]: http://dev.clojure.org/jira/browse/ALGOG
12 | [guidelines]: https://clojure.org/community/contrib_howto
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Eclipse Public License - v 1.0
2 |
3 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
4 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
5 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
6 |
7 | 1. DEFINITIONS
8 |
9 | "Contribution" means:
10 |
11 | a) in the case of the initial Contributor, the initial code and documentation
12 | distributed under this Agreement, and
13 | b) in the case of each subsequent Contributor:
14 | i) changes to the Program, and
15 | ii) additions to the Program;
16 |
17 | where such changes and/or additions to the Program originate from and are
18 | distributed by that particular Contributor. A Contribution 'originates'
19 | from a Contributor if it was added to the Program by such Contributor
20 | itself or anyone acting on such Contributor's behalf. Contributions do not
21 | include additions to the Program which: (i) are separate modules of
22 | software distributed in conjunction with the Program under their own
23 | license agreement, and (ii) are not derivative works of the Program.
24 |
25 | "Contributor" means any person or entity that distributes the Program.
26 |
27 | "Licensed Patents" mean patent claims licensable by a Contributor which are
28 | necessarily infringed by the use or sale of its Contribution alone or when
29 | combined with the Program.
30 |
31 | "Program" means the Contributions distributed in accordance with this
32 | Agreement.
33 |
34 | "Recipient" means anyone who receives the Program under this Agreement,
35 | including all Contributors.
36 |
37 | 2. GRANT OF RIGHTS
38 | a) Subject to the terms of this Agreement, each Contributor hereby grants
39 | Recipient a non-exclusive, worldwide, royalty-free copyright license to
40 | reproduce, prepare derivative works of, publicly display, publicly
41 | perform, distribute and sublicense the Contribution of such Contributor,
42 | if any, and such derivative works, in source code and object code form.
43 | b) Subject to the terms of this Agreement, each Contributor hereby grants
44 | Recipient a non-exclusive, worldwide, royalty-free patent license under
45 | Licensed Patents to make, use, sell, offer to sell, import and otherwise
46 | transfer the Contribution of such Contributor, if any, in source code and
47 | object code form. This patent license shall apply to the combination of
48 | the Contribution and the Program if, at the time the Contribution is
49 | added by the Contributor, such addition of the Contribution causes such
50 | combination to be covered by the Licensed Patents. The patent license
51 | shall not apply to any other combinations which include the Contribution.
52 | No hardware per se is licensed hereunder.
53 | c) Recipient understands that although each Contributor grants the licenses
54 | to its Contributions set forth herein, no assurances are provided by any
55 | Contributor that the Program does not infringe the patent or other
56 | intellectual property rights of any other entity. Each Contributor
57 | disclaims any liability to Recipient for claims brought by any other
58 | entity based on infringement of intellectual property rights or
59 | otherwise. As a condition to exercising the rights and licenses granted
60 | hereunder, each Recipient hereby assumes sole responsibility to secure
61 | any other intellectual property rights needed, if any. For example, if a
62 | third party patent license is required to allow Recipient to distribute
63 | the Program, it is Recipient's responsibility to acquire that license
64 | before distributing the Program.
65 | d) Each Contributor represents that to its knowledge it has sufficient
66 | copyright rights in its Contribution, if any, to grant the copyright
67 | license set forth in this Agreement.
68 |
69 | 3. REQUIREMENTS
70 |
71 | A Contributor may choose to distribute the Program in object code form under
72 | its own license agreement, provided that:
73 |
74 | a) it complies with the terms and conditions of this Agreement; and
75 | b) its license agreement:
76 | i) effectively disclaims on behalf of all Contributors all warranties
77 | and conditions, express and implied, including warranties or
78 | conditions of title and non-infringement, and implied warranties or
79 | conditions of merchantability and fitness for a particular purpose;
80 | ii) effectively excludes on behalf of all Contributors all liability for
81 | damages, including direct, indirect, special, incidental and
82 | consequential damages, such as lost profits;
83 | iii) states that any provisions which differ from this Agreement are
84 | offered by that Contributor alone and not by any other party; and
85 | iv) states that source code for the Program is available from such
86 | Contributor, and informs licensees how to obtain it in a reasonable
87 | manner on or through a medium customarily used for software exchange.
88 |
89 | When the Program is made available in source code form:
90 |
91 | a) it must be made available under this Agreement; and
92 | b) a copy of this Agreement must be included with each copy of the Program.
93 | Contributors may not remove or alter any copyright notices contained
94 | within the Program.
95 |
96 | Each Contributor must identify itself as the originator of its Contribution,
97 | if
98 | any, in a manner that reasonably allows subsequent Recipients to identify the
99 | originator of the Contribution.
100 |
101 | 4. COMMERCIAL DISTRIBUTION
102 |
103 | Commercial distributors of software may accept certain responsibilities with
104 | respect to end users, business partners and the like. While this license is
105 | intended to facilitate the commercial use of the Program, the Contributor who
106 | includes the Program in a commercial product offering should do so in a manner
107 | which does not create potential liability for other Contributors. Therefore,
108 | if a Contributor includes the Program in a commercial product offering, such
109 | Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
110 | every other Contributor ("Indemnified Contributor") against any losses,
111 | damages and costs (collectively "Losses") arising from claims, lawsuits and
112 | other legal actions brought by a third party against the Indemnified
113 | Contributor to the extent caused by the acts or omissions of such Commercial
114 | Contributor in connection with its distribution of the Program in a commercial
115 | product offering. The obligations in this section do not apply to any claims
116 | or Losses relating to any actual or alleged intellectual property
117 | infringement. In order to qualify, an Indemnified Contributor must:
118 | a) promptly notify the Commercial Contributor in writing of such claim, and
119 | b) allow the Commercial Contributor to control, and cooperate with the
120 | Commercial Contributor in, the defense and any related settlement
121 | negotiations. The Indemnified Contributor may participate in any such claim at
122 | its own expense.
123 |
124 | For example, a Contributor might include the Program in a commercial product
125 | offering, Product X. That Contributor is then a Commercial Contributor. If
126 | that Commercial Contributor then makes performance claims, or offers
127 | warranties related to Product X, those performance claims and warranties are
128 | such Commercial Contributor's responsibility alone. Under this section, the
129 | Commercial Contributor would have to defend claims against the other
130 | Contributors related to those performance claims and warranties, and if a
131 | court requires any other Contributor to pay any damages as a result, the
132 | Commercial Contributor must pay those damages.
133 |
134 | 5. NO WARRANTY
135 |
136 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
137 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
138 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
139 | NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
140 | Recipient is solely responsible for determining the appropriateness of using
141 | and distributing the Program and assumes all risks associated with its
142 | exercise of rights under this Agreement , including but not limited to the
143 | risks and costs of program errors, compliance with applicable laws, damage to
144 | or loss of data, programs or equipment, and unavailability or interruption of
145 | operations.
146 |
147 | 6. DISCLAIMER OF LIABILITY
148 |
149 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
150 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
151 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
152 | LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
153 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
154 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
155 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY
156 | OF SUCH DAMAGES.
157 |
158 | 7. GENERAL
159 |
160 | If any provision of this Agreement is invalid or unenforceable under
161 | applicable law, it shall not affect the validity or enforceability of the
162 | remainder of the terms of this Agreement, and without further action by the
163 | parties hereto, such provision shall be reformed to the minimum extent
164 | necessary to make such provision valid and enforceable.
165 |
166 | If Recipient institutes patent litigation against any entity (including a
167 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself
168 | (excluding combinations of the Program with other software or hardware)
169 | infringes such Recipient's patent(s), then such Recipient's rights granted
170 | under Section 2(b) shall terminate as of the date such litigation is filed.
171 |
172 | All Recipient's rights under this Agreement shall terminate if it fails to
173 | comply with any of the material terms or conditions of this Agreement and does
174 | not cure such failure in a reasonable period of time after becoming aware of
175 | such noncompliance. If all Recipient's rights under this Agreement terminate,
176 | Recipient agrees to cease use and distribution of the Program as soon as
177 | reasonably practicable. However, Recipient's obligations under this Agreement
178 | and any licenses granted by Recipient relating to the Program shall continue
179 | and survive.
180 |
181 | Everyone is permitted to copy and distribute copies of this Agreement, but in
182 | order to avoid inconsistency the Agreement is copyrighted and may only be
183 | modified in the following manner. The Agreement Steward reserves the right to
184 | publish new versions (including revisions) of this Agreement from time to
185 | time. No one other than the Agreement Steward has the right to modify this
186 | Agreement. The Eclipse Foundation is the initial Agreement Steward. The
187 | Eclipse Foundation may assign the responsibility to serve as the Agreement
188 | Steward to a suitable separate entity. Each new version of the Agreement will
189 | be given a distinguishing version number. The Program (including
190 | Contributions) may always be distributed subject to the version of the
191 | Agreement under which it was received. In addition, after a new version of the
192 | Agreement is published, Contributor may elect to distribute the Program
193 | (including its Contributions) under the new version. Except as expressly
194 | stated in Sections 2(a) and 2(b) above, Recipient receives no rights or
195 | licenses to the intellectual property of any Contributor under this Agreement,
196 | whether expressly, by implication, estoppel or otherwise. All rights in the
197 | Program not expressly granted under this Agreement are reserved.
198 |
199 | This Agreement is governed by the laws of the State of New York and the
200 | intellectual property laws of the United States of America. No party to this
201 | Agreement will bring a legal action under this Agreement more than one year
202 | after the cause of action arose. Each party waives its rights to a jury trial in
203 | any resulting litigation.
204 |
205 |
206 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # algo.generic
2 |
3 | Generic versions of commonly used functions, implemented as multimethods
4 | that can be implemented for any data type.
5 |
6 | ## Usage
7 |
8 | Each submodule of clojure.algo.generic defines a set of related
9 | multimethods that have the same names as their type-specific
10 | counterparts in clojure.core. Implementations for standard Clojure
11 | data types are provided and behave identically to the clojure.core
12 | versions.
13 |
14 | ### Arities
15 |
16 | Arithmetic and comparison functions are defined for the same arities
17 | that the corresponding clojure.core functions support. Arities higher
18 | than 2 are reduced to unary and binary calls. To provide a multimethod
19 | implementation for binary calls with a given pair of types, use
20 | `[type1 type2]` as the dispatch value. For a unary call, the dispatch
21 | value is `type` as usual. Note that `[type1 type2]` is different from
22 | `[type2 type1]` (in most cases you will want to provide both) and that
23 | `[type type]` (binary operation with both arguments of the same type)
24 | is different from `type` (unary operation).
25 |
26 | ### Root type
27 |
28 | This section applies only to binary operations dispatching on type
29 | pairs, and only for types that are *not* Java classes. Types
30 | created by `deftype` and `defrecord` are Java classes, meaning that
31 | most Clojure programmers can go on with the next section.
32 |
33 | One difficulty with binary operations is that there is no predefined
34 | way to provide a default implementation. For single dispatch there is
35 | `:default`, but there is nothing equivalent to `[:default :default]`.
36 | The algo.generic library therefore defines a *root type*, accessible
37 | as `clojure.algo.generic/root-type`, which is used in the default
38 | implementations of binary operations. To integrate your own type into
39 | this system, you must add the clause `(derive my-type
40 | clojure.algo.generic/root-type)` after your type definition. This is
41 | not required for Java classes because `java.lang.Object` is
42 | already derived from `root-type`.
43 |
44 | ### Submodules
45 |
46 | * **algo.generic.arithmetic** provides generic `+` `-` `*` `/` for all
47 | the arities that the corresponding clojure.core functions support.
48 | The minimal implementations required for full arithmetic on a given
49 | type is binary `+` and `*` and unary `-` and `/`. You may wish to
50 | provide explicit implementations for binary `-` and `/` for
51 | efficiency, otherwise the default implementations are `(- a b) => (+ a (- b))`
52 | and `(/ a b) => (* a (/ b))`.
53 |
54 | * **algo.generic.collection** provides generic versions of `assoc`,
55 | `dissoc`, `get`, `conj`, `empty`, `into`, and `seq`. `into` has a
56 | default implementation in terms of `conj` and `seq`, but you may
57 | wish to provide a more efficient one for your types.
58 |
59 | * **algo.generic.comparison** provides the comparison and test
60 | functions `=`, `not=`, `<`, `>`, `<=`, `>=`, `zero?`, `pos?`,
61 | `neg?`, `min`, and ` max`. `not=`, `min`, and `max` cannot be
62 | redefined, they are standard functions that are implemented in
63 | terms of the generic functions of the module. A minimal
64 | implementation of the binary comparison functions consists of
65 | `=` and `>`. Default implementations for `<`, `<=`, and `>=`
66 | call `>`, but more efficient implementations can be provided.
67 |
68 | * **algo.generic.functor** provides a generic mapping operation
69 | called `fmap`.
70 |
71 | * **algo.generic.math-functions** provides generic versions of the
72 | common math functions from `java.lang.Math`, plus `sgn`, `sqr`, and
73 | `conjugate`.
74 |
75 |
76 | ## Releases and dependency information
77 |
78 | Latest stable release: 0.1.3
79 |
80 | * [All released versions](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22algo.generic%22)
81 |
82 | * [Development Snapshot Versions](https://oss.sonatype.org/index.html#nexus-search;gav~org.clojure~algo.generic~~~)
83 |
84 | [CLI/`deps.edn`](https://clojure.org/reference/deps_and_cli) dependency information:
85 | ```clojure
86 | org.clojure/algo.generic {:mvn/version "0.1.3"}
87 | ```
88 |
89 | [Leiningen](https://github.com/technomancy/leiningen/) dependency information:
90 |
91 | [org.clojure/algo.generic "0.1.3"]
92 |
93 | [Maven](https://maven.apache.org/) dependency information:
94 |
95 |
96 | org.clojure
97 | algo.generic
98 | 0.1.3
99 |
100 |
101 | ## License
102 |
103 | Copyright (c) Rich Hickey and contributors. All rights reserved.
104 |
105 | The use and distribution terms for this software are covered by the
106 | Eclipse Public License 1.0 (https://opensource.org/license/epl-1-0/)
107 | which can be found in the file epl.html at the root of this distribution.
108 | By using this software in any fashion, you are agreeing to be bound by
109 | the terms of this license.
110 | You must not remove this notice, or any other, from this software.
111 |
112 |
113 |
--------------------------------------------------------------------------------
/epl.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Eclipse Public License - Version 1.0
8 |
25 |
26 |
27 |
28 |
29 |
30 | Eclipse Public License - v 1.0
31 |
32 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
33 | PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR
34 | DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS
35 | AGREEMENT.
36 |
37 | 1. DEFINITIONS
38 |
39 | "Contribution" means:
40 |
41 | a) in the case of the initial Contributor, the initial
42 | code and documentation distributed under this Agreement, and
43 | b) in the case of each subsequent Contributor:
44 | i) changes to the Program, and
45 | ii) additions to the Program;
46 | where such changes and/or additions to the Program
47 | originate from and are distributed by that particular Contributor. A
48 | Contribution 'originates' from a Contributor if it was added to the
49 | Program by such Contributor itself or anyone acting on such
50 | Contributor's behalf. Contributions do not include additions to the
51 | Program which: (i) are separate modules of software distributed in
52 | conjunction with the Program under their own license agreement, and (ii)
53 | are not derivative works of the Program.
54 |
55 | "Contributor" means any person or entity that distributes
56 | the Program.
57 |
58 | "Licensed Patents" mean patent claims licensable by a
59 | Contributor which are necessarily infringed by the use or sale of its
60 | Contribution alone or when combined with the Program.
61 |
62 | "Program" means the Contributions distributed in accordance
63 | with this Agreement.
64 |
65 | "Recipient" means anyone who receives the Program under
66 | this Agreement, including all Contributors.
67 |
68 | 2. GRANT OF RIGHTS
69 |
70 | a) Subject to the terms of this Agreement, each
71 | Contributor hereby grants Recipient a non-exclusive, worldwide,
72 | royalty-free copyright license to reproduce, prepare derivative works
73 | of, publicly display, publicly perform, distribute and sublicense the
74 | Contribution of such Contributor, if any, and such derivative works, in
75 | source code and object code form.
76 |
77 | b) Subject to the terms of this Agreement, each
78 | Contributor hereby grants Recipient a non-exclusive, worldwide,
79 | royalty-free patent license under Licensed Patents to make, use, sell,
80 | offer to sell, import and otherwise transfer the Contribution of such
81 | Contributor, if any, in source code and object code form. This patent
82 | license shall apply to the combination of the Contribution and the
83 | Program if, at the time the Contribution is added by the Contributor,
84 | such addition of the Contribution causes such combination to be covered
85 | by the Licensed Patents. The patent license shall not apply to any other
86 | combinations which include the Contribution. No hardware per se is
87 | licensed hereunder.
88 |
89 | c) Recipient understands that although each Contributor
90 | grants the licenses to its Contributions set forth herein, no assurances
91 | are provided by any Contributor that the Program does not infringe the
92 | patent or other intellectual property rights of any other entity. Each
93 | Contributor disclaims any liability to Recipient for claims brought by
94 | any other entity based on infringement of intellectual property rights
95 | or otherwise. As a condition to exercising the rights and licenses
96 | granted hereunder, each Recipient hereby assumes sole responsibility to
97 | secure any other intellectual property rights needed, if any. For
98 | example, if a third party patent license is required to allow Recipient
99 | to distribute the Program, it is Recipient's responsibility to acquire
100 | that license before distributing the Program.
101 |
102 | d) Each Contributor represents that to its knowledge it
103 | has sufficient copyright rights in its Contribution, if any, to grant
104 | the copyright license set forth in this Agreement.
105 |
106 | 3. REQUIREMENTS
107 |
108 | A Contributor may choose to distribute the Program in object code
109 | form under its own license agreement, provided that:
110 |
111 | a) it complies with the terms and conditions of this
112 | Agreement; and
113 |
114 | b) its license agreement:
115 |
116 | i) effectively disclaims on behalf of all Contributors
117 | all warranties and conditions, express and implied, including warranties
118 | or conditions of title and non-infringement, and implied warranties or
119 | conditions of merchantability and fitness for a particular purpose;
120 |
121 | ii) effectively excludes on behalf of all Contributors
122 | all liability for damages, including direct, indirect, special,
123 | incidental and consequential damages, such as lost profits;
124 |
125 | iii) states that any provisions which differ from this
126 | Agreement are offered by that Contributor alone and not by any other
127 | party; and
128 |
129 | iv) states that source code for the Program is available
130 | from such Contributor, and informs licensees how to obtain it in a
131 | reasonable manner on or through a medium customarily used for software
132 | exchange.
133 |
134 | When the Program is made available in source code form:
135 |
136 | a) it must be made available under this Agreement; and
137 |
138 | b) a copy of this Agreement must be included with each
139 | copy of the Program.
140 |
141 | Contributors may not remove or alter any copyright notices contained
142 | within the Program.
143 |
144 | Each Contributor must identify itself as the originator of its
145 | Contribution, if any, in a manner that reasonably allows subsequent
146 | Recipients to identify the originator of the Contribution.
147 |
148 | 4. COMMERCIAL DISTRIBUTION
149 |
150 | Commercial distributors of software may accept certain
151 | responsibilities with respect to end users, business partners and the
152 | like. While this license is intended to facilitate the commercial use of
153 | the Program, the Contributor who includes the Program in a commercial
154 | product offering should do so in a manner which does not create
155 | potential liability for other Contributors. Therefore, if a Contributor
156 | includes the Program in a commercial product offering, such Contributor
157 | ("Commercial Contributor") hereby agrees to defend and
158 | indemnify every other Contributor ("Indemnified Contributor")
159 | against any losses, damages and costs (collectively "Losses")
160 | arising from claims, lawsuits and other legal actions brought by a third
161 | party against the Indemnified Contributor to the extent caused by the
162 | acts or omissions of such Commercial Contributor in connection with its
163 | distribution of the Program in a commercial product offering. The
164 | obligations in this section do not apply to any claims or Losses
165 | relating to any actual or alleged intellectual property infringement. In
166 | order to qualify, an Indemnified Contributor must: a) promptly notify
167 | the Commercial Contributor in writing of such claim, and b) allow the
168 | Commercial Contributor to control, and cooperate with the Commercial
169 | Contributor in, the defense and any related settlement negotiations. The
170 | Indemnified Contributor may participate in any such claim at its own
171 | expense.
172 |
173 | For example, a Contributor might include the Program in a commercial
174 | product offering, Product X. That Contributor is then a Commercial
175 | Contributor. If that Commercial Contributor then makes performance
176 | claims, or offers warranties related to Product X, those performance
177 | claims and warranties are such Commercial Contributor's responsibility
178 | alone. Under this section, the Commercial Contributor would have to
179 | defend claims against the other Contributors related to those
180 | performance claims and warranties, and if a court requires any other
181 | Contributor to pay any damages as a result, the Commercial Contributor
182 | must pay those damages.
183 |
184 | 5. NO WARRANTY
185 |
186 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
187 | PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
188 | OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION,
189 | ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
190 | OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
191 | responsible for determining the appropriateness of using and
192 | distributing the Program and assumes all risks associated with its
193 | exercise of rights under this Agreement , including but not limited to
194 | the risks and costs of program errors, compliance with applicable laws,
195 | damage to or loss of data, programs or equipment, and unavailability or
196 | interruption of operations.
197 |
198 | 6. DISCLAIMER OF LIABILITY
199 |
200 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
201 | NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
202 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
203 | WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
204 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
205 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
206 | DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
207 | HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
208 |
209 | 7. GENERAL
210 |
211 | If any provision of this Agreement is invalid or unenforceable under
212 | applicable law, it shall not affect the validity or enforceability of
213 | the remainder of the terms of this Agreement, and without further action
214 | by the parties hereto, such provision shall be reformed to the minimum
215 | extent necessary to make such provision valid and enforceable.
216 |
217 | If Recipient institutes patent litigation against any entity
218 | (including a cross-claim or counterclaim in a lawsuit) alleging that the
219 | Program itself (excluding combinations of the Program with other
220 | software or hardware) infringes such Recipient's patent(s), then such
221 | Recipient's rights granted under Section 2(b) shall terminate as of the
222 | date such litigation is filed.
223 |
224 | All Recipient's rights under this Agreement shall terminate if it
225 | fails to comply with any of the material terms or conditions of this
226 | Agreement and does not cure such failure in a reasonable period of time
227 | after becoming aware of such noncompliance. If all Recipient's rights
228 | under this Agreement terminate, Recipient agrees to cease use and
229 | distribution of the Program as soon as reasonably practicable. However,
230 | Recipient's obligations under this Agreement and any licenses granted by
231 | Recipient relating to the Program shall continue and survive.
232 |
233 | Everyone is permitted to copy and distribute copies of this
234 | Agreement, but in order to avoid inconsistency the Agreement is
235 | copyrighted and may only be modified in the following manner. The
236 | Agreement Steward reserves the right to publish new versions (including
237 | revisions) of this Agreement from time to time. No one other than the
238 | Agreement Steward has the right to modify this Agreement. The Eclipse
239 | Foundation is the initial Agreement Steward. The Eclipse Foundation may
240 | assign the responsibility to serve as the Agreement Steward to a
241 | suitable separate entity. Each new version of the Agreement will be
242 | given a distinguishing version number. The Program (including
243 | Contributions) may always be distributed subject to the version of the
244 | Agreement under which it was received. In addition, after a new version
245 | of the Agreement is published, Contributor may elect to distribute the
246 | Program (including its Contributions) under the new version. Except as
247 | expressly stated in Sections 2(a) and 2(b) above, Recipient receives no
248 | rights or licenses to the intellectual property of any Contributor under
249 | this Agreement, whether expressly, by implication, estoppel or
250 | otherwise. All rights in the Program not expressly granted under this
251 | Agreement are reserved.
252 |
253 | This Agreement is governed by the laws of the State of New York and
254 | the intellectual property laws of the United States of America. No party
255 | to this Agreement will bring a legal action under this Agreement more
256 | than one year after the cause of action arose. Each party waives its
257 | rights to a jury trial in any resulting litigation.
258 |
259 |
260 |
261 |
262 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | algo.generic
4 | 1.0.2-SNAPSHOT
5 | algo.generic
6 |
7 |
8 | org.clojure
9 | pom.contrib
10 | 1.3.0
11 |
12 |
13 |
14 |
15 | Konrad Hinsen
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | scm:git:git@github.com:clojure/algo.generic.git
24 | scm:git:git@github.com:clojure/algo.generic.git
25 | git@github.com:clojure/algo.generic.git
26 | HEAD
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/main/clojure/clojure/algo/generic.clj:
--------------------------------------------------------------------------------
1 | ;; Support code for generic interfaces
2 |
3 | ;; by Konrad Hinsen
4 |
5 | ;; Copyright (c) Konrad Hinsen, 2009-2011. All rights reserved. The use
6 | ;; and distribution terms for this software are covered by the Eclipse
7 | ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
8 | ;; which can be found in the file epl-v10.html at the root of this
9 | ;; distribution. By using this software in any fashion, you are
10 | ;; agreeing to be bound by the terms of this license. You must not
11 | ;; remove this notice, or any other, from this software.
12 |
13 | (ns
14 | ^{:author "Konrad Hinsen"
15 | :skip-wiki true
16 | :doc "Generic interfaces
17 | This library provides generic interfaces in the form of
18 | multimethods that can be implemented for any type.
19 | The interfaces partly duplicate existing non-generic
20 | functions in clojure.core (arithmetic, comparison,
21 | collections) and partly provide additional functions that
22 | can be defined for a wide variety of types (functors, math
23 | functions)."}
24 | clojure.algo.generic)
25 |
26 | ;
27 | ; A dispatch function that separates nulary, unary, binary, and
28 | ; higher arity calls and also selects on type for unary and binary
29 | ; calls.
30 | ;
31 | (defn nary-dispatch
32 | ([] ::nulary)
33 | ([x] (type x))
34 | ([x y]
35 | [(type x) (type y)])
36 | ([x y & more] ::nary))
37 |
38 | ;
39 | ; We can't use [::binary :default], so we need to define a root type
40 | ; of the type hierarcy. The derivation for Object covers all classes,
41 | ; but all non-class types will need an explicit derive clause.
42 | ; Since non-class types are rare since Clojure 1.2, this need is
43 | ; not likely to be frequent.
44 | ;
45 | (def root-type ::any)
46 | (derive Object root-type)
47 |
48 | ;
49 | ; Symbols referring to ::nulary and ::n-ary
50 | ;
51 | (def nulary-type ::nulary)
52 | (def nary-type ::nary)
53 |
54 |
--------------------------------------------------------------------------------
/src/main/clojure/clojure/algo/generic/arithmetic.clj:
--------------------------------------------------------------------------------
1 | ;; Generic interfaces for arithmetic operations
2 |
3 | ;; by Konrad Hinsen
4 |
5 | ;; Copyright (c) Konrad Hinsen, 2009-2011. All rights reserved. The use
6 | ;; and distribution terms for this software are covered by the Eclipse
7 | ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
8 | ;; which can be found in the file epl-v10.html at the root of this
9 | ;; distribution. By using this software in any fashion, you are
10 | ;; agreeing to be bound by the terms of this license. You must not
11 | ;; remove this notice, or any other, from this software.
12 |
13 | (ns
14 | ^{:author "Konrad Hinsen"
15 | :doc "Generic arithmetic interface
16 | This library defines generic versions of + - * / as multimethods
17 | that can be defined for any type. The minimal required
18 | implementations for a type are binary + and * plus unary - and /.
19 | Everything else is derived from these automatically. Explicit
20 | binary definitions for - and / can be provided for
21 | efficiency reasons."}
22 | clojure.algo.generic.arithmetic
23 | (:use [clojure.algo.generic
24 | :only (root-type nulary-type nary-type nary-dispatch)])
25 | (:refer-clojure :exclude [+ - * /]))
26 |
27 | ;
28 | ; Universal zero and one values
29 | ;
30 | (defrecord zero-type [])
31 | (derive zero-type root-type)
32 | (def zero (new zero-type))
33 |
34 | (defrecord one-type [])
35 | (derive one-type root-type)
36 | (def one (new one-type))
37 |
38 | ;
39 | ; Addition
40 | ;
41 | ; The minimal implementation is for binary my-type. It is possible
42 | ; in principle to implement [::unary my-type] as well, though this
43 | ; doesn't make any sense.
44 | ;
45 | (defmulti +
46 | "Return the sum of all arguments. The minimal implementation for type
47 | ::my-type is the binary form with dispatch value [::my-type ::my-type]."
48 | {:arglists '([x] [x y] [x y & more])}
49 | nary-dispatch)
50 |
51 | (defmethod + nulary-type
52 | []
53 | zero)
54 |
55 | (defmethod + root-type
56 | [x] x)
57 |
58 | (defmethod + [root-type zero-type]
59 | [x y] x)
60 |
61 | (defmethod + [zero-type root-type]
62 | [x y] y)
63 |
64 | (defmethod + nary-type
65 | [x y & more]
66 | (if more
67 | (recur (+ x y) (first more) (next more))
68 | (+ x y)))
69 |
70 | ;
71 | ; Subtraction
72 | ;
73 | ; The minimal implementation is for unary my-type. A default binary
74 | ; implementation is provided as (+ x (- y)), but it is possible to
75 | ; implement unary my-type explicitly for efficiency reasons.
76 | ;
77 | (defmulti -
78 | "Return the difference of the first argument and the sum of all other
79 | arguments. The minimal implementation for type ::my-type is the binary
80 | form with dispatch value [::my-type ::my-type]."
81 | {:arglists '([x] [x y] [x y & more])}
82 | nary-dispatch)
83 |
84 | (defmethod - nulary-type
85 | []
86 | (throw (java.lang.IllegalArgumentException.
87 | "Wrong number of arguments passed")))
88 |
89 | (defmethod - [root-type zero-type]
90 | [x y] x)
91 |
92 | (defmethod - [zero-type root-type]
93 | [x y] (- y))
94 |
95 | (defmethod - [root-type root-type]
96 | [x y] (+ x (- y)))
97 |
98 | (defmethod - nary-type
99 | [x y & more]
100 | (if more
101 | (recur (- x y) (first more) (next more))
102 | (- x y)))
103 |
104 | ;
105 | ; Multiplication
106 | ;
107 | ; The minimal implementation is for binary [my-type my-type]. It is possible
108 | ; in principle to implement unary my-type as well, though this
109 | ; doesn't make any sense.
110 | ;
111 | (defmulti *
112 | "Return the product of all arguments. The minimal implementation for type
113 | ::my-type is the binary form with dispatch value [::my-type ::my-type]."
114 | {:arglists '([x] [x y] [x y & more])}
115 | nary-dispatch)
116 |
117 | (defmethod * nulary-type
118 | []
119 | one)
120 |
121 | (defmethod * root-type
122 | [x] x)
123 |
124 | (defmethod * [root-type one-type]
125 | [x y] x)
126 |
127 | (defmethod * [one-type root-type]
128 | [x y] y)
129 |
130 | (defmethod * nary-type
131 | [x y & more]
132 | (if more
133 | (recur (* x y) (first more) (next more))
134 | (* x y)))
135 |
136 | ;
137 | ; Division
138 | ;
139 | ; The minimal implementation is for unary my-type. A default binary
140 | ; implementation is provided as (* x (/ y)), but it is possible to
141 | ; implement binary [my-type my-type] explicitly for efficiency reasons.
142 | ;
143 | (defmulti /
144 | "Return the quotient of the first argument and the product of all other
145 | arguments. The minimal implementation for type ::my-type is the binary
146 | form with dispatch value [::my-type ::my-type]."
147 | {:arglists '([x] [x y] [x y & more])}
148 | nary-dispatch)
149 |
150 | (defmethod / nulary-type
151 | []
152 | (throw (java.lang.IllegalArgumentException.
153 | "Wrong number of arguments passed")))
154 |
155 | (defmethod / [root-type one-type]
156 | [x y] x)
157 |
158 | (defmethod / [one-type root-type]
159 | [x y] (/ y))
160 |
161 | (defmethod / [root-type root-type]
162 | [x y] (* x (/ y)))
163 |
164 | (defmethod / nary-type
165 | [x y & more]
166 | (if more
167 | (recur (/ x y) (first more) (next more))
168 | (/ x y)))
169 |
170 | ;
171 | ; Macros to permit access to the / multimethod via namespace qualification
172 | ;
173 | (defmacro defmethod*
174 | "Define a method implementation for the multimethod name in namespace ns.
175 | Required for implementing the division function from another namespace."
176 | [ns name & args]
177 | (let [qsym (symbol (str ns) (str name))]
178 | `(defmethod ~qsym ~@args)))
179 |
180 | (defmacro qsym
181 | "Create the qualified symbol corresponding to sym in namespace ns.
182 | Required to access the division function from another namespace,
183 | e.g. as (qsym clojure.algo.generic.arithmetic /)."
184 | [ns sym]
185 | (symbol (str ns) (str sym)))
186 |
187 | ;
188 | ; Minimal implementations for java.lang.Number
189 | ;
190 | (defmethod + [java.lang.Number java.lang.Number]
191 | [x y] (clojure.core/+ x y))
192 |
193 | (defmethod - java.lang.Number
194 | [x] (clojure.core/- x))
195 |
196 | (defmethod * [java.lang.Number java.lang.Number]
197 | [x y] (clojure.core/* x y))
198 |
199 | (defmethod / java.lang.Number
200 | [x] (clojure.core// x))
201 |
202 |
--------------------------------------------------------------------------------
/src/main/clojure/clojure/algo/generic/collection.clj:
--------------------------------------------------------------------------------
1 | ;; Generic interfaces for collection-related functions
2 |
3 | ;; by Konrad Hinsen
4 |
5 | ;; Copyright (c) Konrad Hinsen, 2009-2011. All rights reserved. The use
6 | ;; and distribution terms for this software are covered by the Eclipse
7 | ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
8 | ;; which can be found in the file epl-v10.html at the root of this
9 | ;; distribution. By using this software in any fashion, you are
10 | ;; agreeing to be bound by the terms of this license. You must not
11 | ;; remove this notice, or any other, from this software.
12 |
13 | (ns
14 | ^{:author "Konrad Hinsen"
15 | :doc "Generic collection interface
16 | This library defines generic versions of common
17 | collection-related functions as multimethods that can be
18 | defined for any type."}
19 | clojure.algo.generic.collection
20 | (:refer-clojure :exclude [assoc conj dissoc empty get into seq]))
21 |
22 | ;
23 | ; assoc
24 | ;
25 | (defmulti assoc
26 | "Returns a new collection in which the values corresponding to the
27 | given keys are updated by the given values. Each type of collection
28 | can have specific restrictions on the possible keys."
29 | {:arglists '([coll & key-val-pairs])}
30 | (fn [coll & items] (type coll)))
31 |
32 | (defmethod assoc :default
33 | [map & key-val-pairs]
34 | (apply clojure.core/assoc map key-val-pairs))
35 |
36 | ;
37 | ; conj
38 | ;
39 | (defmulti conj
40 | "Returns a new collection resulting from adding all xs to coll."
41 | {:arglists '([coll & xs])}
42 | (fn [coll & xs] (type coll)))
43 |
44 | (defmethod conj :default
45 | [coll & xs]
46 | (apply clojure.core/conj coll xs))
47 |
48 | ;
49 | ; dissoc
50 | ;
51 | (defmulti dissoc
52 | "Returns a new collection in which the entries corresponding to the
53 | given keys are removed. Each type of collection can have specific
54 | restrictions on the possible keys."
55 | {:arglists '([coll & keys])}
56 | (fn [coll & keys] (type coll)))
57 |
58 | (defmethod dissoc :default
59 | [map & keys]
60 | (apply clojure.core/dissoc map keys))
61 |
62 | ;
63 | ; empty
64 | ;
65 | (defmulti empty
66 | "Returns an empty collection of the same kind as the argument"
67 | {:arglists '([coll])}
68 | type)
69 |
70 | (defmethod empty :default
71 | [coll]
72 | (clojure.core/empty coll))
73 |
74 | ;
75 | ; get
76 | ;
77 | (defmulti get
78 | "Returns the element of coll referred to by key. Each type of collection
79 | can have specific restrictions on the possible keys."
80 | {:arglists '([coll key] [coll key not-found])}
81 | (fn [coll & args] (type coll)))
82 |
83 | (defmethod get :default
84 | ([coll key]
85 | (clojure.core/get coll key))
86 | ([coll key not-found]
87 | (clojure.core/get coll key not-found)))
88 |
89 | ;
90 | ; into
91 | ;
92 | (defmulti into
93 | "Returns a new coll consisting of to-coll with all of the items of
94 | from-coll conjoined. A default implementation based on reduce, conj, and
95 | seq is provided."
96 | {:arglists '([to from])}
97 | (fn [to from] (type to)))
98 |
99 | (declare seq)
100 | (defmethod into :default
101 | [to from]
102 | (reduce conj to (seq from)))
103 |
104 | ;
105 | ; seq
106 | ;
107 | (defmulti seq
108 | "Returns a seq on the object s."
109 | {:arglists '([s])}
110 | type)
111 |
112 | (defmethod seq :default
113 | [s]
114 | (clojure.core/seq s))
115 |
--------------------------------------------------------------------------------
/src/main/clojure/clojure/algo/generic/comparison.clj:
--------------------------------------------------------------------------------
1 | ;; Generic interfaces for comparison operations
2 |
3 | ;; by Konrad Hinsen
4 |
5 | ;; Copyright (c) Konrad Hinsen, 2009-2011. All rights reserved. The use
6 | ;; and distribution terms for this software are covered by the Eclipse
7 | ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
8 | ;; which can be found in the file epl-v10.html at the root of this
9 | ;; distribution. By using this software in any fashion, you are
10 | ;; agreeing to be bound by the terms of this license. You must not
11 | ;; remove this notice, or any other, from this software.
12 |
13 | (ns
14 | ^{:author "Konrad Hinsen"
15 | :doc "Generic comparison interface
16 | This library defines generic versions of = not= < > <= >= zero?
17 | as multimethods that can be defined for any type. Of the
18 | greater/less-than relations, types must minimally implement >."}
19 | clojure.algo.generic.comparison
20 | (:refer-clojure :exclude [= not= < > <= >= zero? pos? neg? min max])
21 | (:use [clojure.algo.generic
22 | :only (root-type nulary-type nary-type nary-dispatch)]))
23 |
24 | ;
25 | ; zero? pos? neg?
26 | ;
27 | (defmulti zero?
28 | "Return true of x is zero."
29 | {:arglists '([x])}
30 | type)
31 |
32 | (defmulti pos?
33 | "Return true of x is positive."
34 | {:arglists '([x])}
35 | type)
36 |
37 | (defmulti neg?
38 | "Return true of x is negative."
39 | {:arglists '([x])}
40 | type)
41 |
42 | ;
43 | ; Equality
44 | ;
45 | (defmulti =
46 | "Return true if all arguments are equal. The minimal implementation for type
47 | ::my-type is the binary form with dispatch value [::my-type ::my-type]."
48 | {:arglists '([x] [x y] [x y & more])}
49 | nary-dispatch)
50 |
51 | (defmethod = root-type
52 | [x] true)
53 |
54 | (defmethod = nary-type
55 | [x y & more]
56 | (if (= x y)
57 | (if (next more)
58 | (recur y (first more) (next more))
59 | (= y (first more)))
60 | false))
61 |
62 | (defn not=
63 | "Equivalent to (not (= ...))."
64 | [& args]
65 | (not (apply = args)))
66 |
67 | ;
68 | ; Greater-than
69 | ;
70 | (defmulti >
71 | "Return true if each argument is larger than the following ones.
72 | The minimal implementation for type ::my-type is the binary form
73 | with dispatch value [::my-type ::my-type]."
74 | {:arglists '([x] [x y] [x y & more])}
75 | nary-dispatch)
76 |
77 | (defmethod > root-type
78 | [x] true)
79 |
80 | (defmethod > nary-type
81 | [x y & more]
82 | (if (> x y)
83 | (if (next more)
84 | (recur y (first more) (next more))
85 | (> y (first more)))
86 | false))
87 |
88 | ;
89 | ; Less-than defaults to greater-than with arguments inversed
90 | ;
91 | (defmulti <
92 | "Return true if each argument is smaller than the following ones.
93 | The minimal implementation for type ::my-type is the binary form
94 | with dispatch value [::my-type ::my-type]. A default implementation
95 | is provided in terms of >."
96 | {:arglists '([x] [x y] [x y & more])}
97 | nary-dispatch)
98 |
99 | (defmethod < root-type
100 | [x] true)
101 |
102 | (defmethod < [root-type root-type]
103 | [x y]
104 | (> y x))
105 |
106 | (defmethod < nary-type
107 | [x y & more]
108 | (if (< x y)
109 | (if (next more)
110 | (recur y (first more) (next more))
111 | (< y (first more)))
112 | false))
113 |
114 | ;
115 | ; Greater-or-equal defaults to (complement <)
116 | ;
117 | (defmulti >=
118 | "Return true if each argument is larger than or equal to the following
119 | ones. The minimal implementation for type ::my-type is the binary form
120 | with dispatch value [::my-type ::my-type]. A default implementation
121 | is provided in terms of <."
122 | {:arglists '([x] [x y] [x y & more])}
123 | nary-dispatch)
124 |
125 | (defmethod >= root-type
126 | [x] true)
127 |
128 | (defmethod >= [root-type root-type]
129 | [x y]
130 | (not (< x y)))
131 |
132 | (defmethod >= nary-type
133 | [x y & more]
134 | (if (>= x y)
135 | (if (next more)
136 | (recur y (first more) (next more))
137 | (>= y (first more)))
138 | false))
139 |
140 | ;
141 | ; Less-than defaults to (complement >)
142 | ;
143 | (defmulti <=
144 | "Return true if each arguments is smaller than or equal to the following
145 | ones. The minimal implementation for type ::my-type is the binary form
146 | with dispatch value [::my-type ::my-type]. A default implementation
147 | is provided in terms of >."
148 | {:arglists '([x] [x y] [x y & more])}
149 | nary-dispatch)
150 |
151 | (defmethod <= root-type
152 | [x] true)
153 |
154 | (defmethod <= [root-type root-type]
155 | [x y]
156 | (not (> x y)))
157 |
158 | (defmethod <= nary-type
159 | [x y & more]
160 | (if (<= x y)
161 | (if (next more)
162 | (recur y (first more) (next more))
163 | (<= y (first more)))
164 | false))
165 |
166 | ;
167 | ; Implementations for Clojure's built-in types
168 | ;
169 | (defmethod zero? java.lang.Number
170 | [x]
171 | (clojure.core/zero? x))
172 |
173 | (defmethod pos? java.lang.Number
174 | [x]
175 | (clojure.core/pos? x))
176 |
177 | (defmethod neg? java.lang.Number
178 | [x]
179 | (clojure.core/neg? x))
180 |
181 | (defmethod = [root-type root-type]
182 | [x y]
183 | (clojure.core/= x y))
184 |
185 | (defmethod > [java.lang.Number java.lang.Number]
186 | [x y]
187 | (clojure.core/> x y))
188 |
189 | (defmethod < [java.lang.Number java.lang.Number]
190 | [x y]
191 | (clojure.core/< x y))
192 |
193 | (defmethod >= [java.lang.Number java.lang.Number]
194 | [x y]
195 | (clojure.core/>= x y))
196 |
197 | (defmethod <= [java.lang.Number java.lang.Number]
198 | [x y]
199 | (clojure.core/<= x y))
200 |
201 | ;
202 | ; Functions defined in terms of the comparison operators
203 | ;
204 | (defn max
205 | "Returns the greatest of its arguments. Like clojure.core/max except that
206 | is uses generic comparison functions implementable for any data type."
207 | ([x] x)
208 | ([x y] (if (> x y) x y))
209 | ([x y & more]
210 | (reduce max (max x y) more)))
211 |
212 | (defn min
213 | "Returns the least of its arguments. Like clojure.core/min except that
214 | is uses generic comparison functions implementable for any data type."
215 | ([x] x)
216 | ([x y] (if (< x y) x y))
217 | ([x y & more]
218 | (reduce min (min x y) more)))
219 |
--------------------------------------------------------------------------------
/src/main/clojure/clojure/algo/generic/functor.clj:
--------------------------------------------------------------------------------
1 | ;; Generic interface for functors
2 |
3 | ;; by Konrad Hinsen
4 |
5 | ;; Copyright (c) Konrad Hinsen, 2009-2011. All rights reserved. The use
6 | ;; and distribution terms for this software are covered by the Eclipse
7 | ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
8 | ;; which can be found in the file epl-v10.html at the root of this
9 | ;; distribution. By using this software in any fashion, you are
10 | ;; agreeing to be bound by the terms of this license. You must not
11 | ;; remove this notice, or any other, from this software.
12 |
13 | (ns
14 | ^{:author "Konrad Hinsen"
15 | :doc "Generic functor interface (fmap)"}
16 | clojure.algo.generic.functor)
17 |
18 |
19 | (defmulti fmap
20 | "Applies function f to each item in the data structure s and returns
21 | a structure of the same kind."
22 | {:arglists '([f s])}
23 | (fn [f s] (type s)))
24 |
25 | (defmethod fmap clojure.lang.IPersistentList
26 | [f v]
27 | (map f v))
28 |
29 | (defmethod fmap clojure.lang.IPersistentVector
30 | [f v]
31 | (into (empty v) (map f v)))
32 |
33 | (defmethod fmap clojure.lang.IPersistentMap
34 | [f m]
35 | (into (empty m) (for [[k v] m] [k (f v)])))
36 |
37 | (defmethod fmap clojure.lang.IPersistentSet
38 | [f s]
39 | (into (empty s) (map f s)))
40 |
41 | (defmethod fmap clojure.lang.IFn
42 | [f fn]
43 | (comp f fn))
44 |
45 | (prefer-method fmap clojure.lang.IPersistentVector clojure.lang.IFn)
46 | (prefer-method fmap clojure.lang.IPersistentMap clojure.lang.IFn)
47 | (prefer-method fmap clojure.lang.IPersistentSet clojure.lang.IFn)
48 | (prefer-method fmap clojure.lang.IPersistentList clojure.lang.ISeq)
49 |
50 | (defmethod fmap clojure.lang.ISeq
51 | [f s]
52 | (map f s))
53 |
54 | (defmethod fmap java.util.concurrent.Future
55 | [f o]
56 | (future (f @o)))
57 |
58 | (defmethod fmap clojure.lang.Delay
59 | [f d]
60 | (delay (f @d)))
61 |
62 | (defmethod fmap nil
63 | [_ _]
64 | nil)
65 |
--------------------------------------------------------------------------------
/src/main/clojure/clojure/algo/generic/math_functions.clj:
--------------------------------------------------------------------------------
1 | ;; Generic interfaces for mathematical functions
2 |
3 | ;; by Konrad Hinsen
4 |
5 | ;; Copyright (c) Konrad Hinsen, 2009-2011. All rights reserved. The use
6 | ;; and distribution terms for this software are covered by the Eclipse
7 | ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
8 | ;; which can be found in the file epl-v10.html at the root of this
9 | ;; distribution. By using this software in any fashion, you are
10 | ;; agreeing to be bound by the terms of this license. You must not
11 | ;; remove this notice, or any other, from this software.
12 |
13 | ;; Cort Spellman, 2015:
14 | ;; Changes of abs and round to be manually defined for various types instead
15 | ;; of via defmathfn-1.
16 |
17 | (ns
18 | ^{:author "Konrad Hinsen"
19 | :doc "Generic math function interface
20 | This library defines generic versions of common mathematical
21 | functions such as sqrt or sin as multimethods that can be
22 | defined for any type."}
23 | clojure.algo.generic.math-functions
24 | (:refer-clojure :exclude [abs])
25 | (:require [clojure.algo.generic.arithmetic :as ga]
26 | [clojure.algo.generic.comparison :as gc]))
27 |
28 | ; This used to be in clojure.contrib.def (by Steve Gilardi),
29 | ; which has not been migrated to the new contrib collection.
30 | (defmacro defmacro-
31 | "Same as defmacro but yields a private definition"
32 | [name & decls]
33 | (list* `defmacro (with-meta name (assoc (meta name) :private true)) decls))
34 |
35 | ; One-argument math functions
36 | (defmacro- defmathfn-1
37 | [name]
38 | (let [java-symbol (symbol "java.lang.Math" (str name))]
39 | `(do
40 | (defmulti ~name
41 | ~(str "Return the " name " of x.")
42 | {:arglists '([~'x])}
43 | type)
44 | (defmethod ~name java.lang.Number
45 | [~'x]
46 | (~java-symbol ~'x)))))
47 |
48 | (defn- two-types [x y] [(type x) (type y)])
49 |
50 | ; Two-argument math functions
51 | (defmacro- defmathfn-2
52 | [name]
53 | (let [java-symbol (symbol "java.lang.Math" (str name))]
54 | `(do
55 | (defmulti ~name
56 | ~(str "Return the " name " of x and y.")
57 | {:arglists '([~'x ~'y])}
58 | two-types)
59 | (defmethod ~name [java.lang.Number java.lang.Number]
60 | [~'x ~'y]
61 | (~java-symbol ~'x ~'y)))))
62 |
63 | ; List of math functions taken from
64 | ; http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Math.html
65 | (defmathfn-1 acos)
66 | (defmathfn-1 asin)
67 | (defmathfn-1 atan)
68 | (defmathfn-2 atan2)
69 | (defmathfn-1 ceil)
70 | (defmathfn-1 cos)
71 | (defmathfn-1 exp)
72 | (defmathfn-1 floor)
73 | (defmathfn-1 log)
74 | (defmathfn-2 pow)
75 | (defmathfn-1 rint)
76 | (defmathfn-1 sin)
77 | (defmathfn-1 sqrt)
78 | (defmathfn-1 tan)
79 |
80 | ;
81 | ; Absolute value
82 | ; defmathfn-1 only works for types of numbers for which java.Math has an abs
83 | ; method:
84 | ; * java.math.BigInteger and java.math.BigDecimal classes define their own abs
85 | ; methods.
86 | ; * clojure.lang.BigInt may internally be a long or a BigInteger but in either
87 | ; case clojure.lang.BigInt does not have an abs method.
88 | ; * clojure.lang.Ratio does not have an abs method.
89 | ;
90 | (defmulti abs
91 | "Return the absolute value of x. If x is a BigDecimal, abs takes an optional
92 | math-context argument."
93 | {:arglists '([x] [x math-context])}
94 | (fn [x & more] (type x)))
95 |
96 | (defmethod abs :default
97 | [x]
98 | (cond (gc/neg? x) (- x)
99 | :else x))
100 |
101 | (defmethod abs java.lang.Number
102 | [x]
103 | (java.lang.Math/abs x))
104 |
105 | (defmethod abs java.math.BigDecimal
106 | ([x]
107 | (.abs x))
108 | ([x math-context]
109 | (.abs x math-context)))
110 |
111 | (defmethod abs java.math.BigInteger
112 | [x]
113 | (.abs x))
114 |
115 | (defmethod abs clojure.lang.BigInt
116 | [x]
117 | (if (nil? (.bipart x))
118 | (clojure.lang.BigInt/fromLong (abs (.lpart x)))
119 | (clojure.lang.BigInt/fromBigInteger (abs (.bipart x)))))
120 |
121 | (defmethod abs clojure.lang.Ratio
122 | [x]
123 | (/ (abs (numerator x))
124 | (abs (denominator x))))
125 |
126 | ;
127 | ; Round
128 | ; defmathfn-1 only works for types of numbers for which java.Math has an abs
129 | ; method:
130 | ; * java.math.BigInteger and java.math.BigDecimal classes define their own round
131 | ; methods.
132 | ; * clojure.lang.BigInt may internally be a long or a BigInteger but in either
133 | ; case clojure.lang.BigInt does not have an round method.
134 | ; * clojure.lang.Ratio does not have an round method.
135 | ;
136 | (defmulti round
137 | "Round x.
138 | If x is a BigDecimal, a math-context argument is also required:
139 | (round x math-context)
140 | If x is a Ratio,
141 | (round x) converts x to a double and rounds;
142 | (round x math-context) converts x to a BigDecimal and rounds."
143 | {:arglists '([x] [x math-context])}
144 | (fn [x & more] (type x)))
145 |
146 | (doseq [c [java.lang.Float
147 | java.lang.Double]]
148 | (defmethod round c [x] (java.lang.Math/round x)))
149 |
150 | (doseq [c [java.lang.Byte
151 | java.lang.Short
152 | java.lang.Integer
153 | java.lang.Long
154 | java.math.BigInteger
155 | clojure.lang.BigInt]]
156 | (defmethod round c [x] x))
157 |
158 | (defmethod round java.math.BigDecimal
159 | [x math-context]
160 | (.round x math-context))
161 |
162 | (defmethod round clojure.lang.Ratio
163 | ([x]
164 | (round (double x)))
165 | ([x math-context]
166 | (round (bigdec x) math-context)))
167 |
168 |
169 | ;
170 | ; Sign
171 | ;
172 | (defmulti sgn
173 | "Return the sign of x (-1, 0, or 1)."
174 | {:arglists '([x])}
175 | type)
176 |
177 | (defmethod sgn :default
178 | [x]
179 | (cond (gc/zero? x) 0
180 | (gc/> x 0) 1
181 | :else -1))
182 |
183 | ;
184 | ; Conjugation
185 | ;
186 | (defmulti conjugate
187 | "Return the conjugate of x."
188 | {:arglists '([x])}
189 | type)
190 |
191 | (defmethod conjugate :default
192 | [x] x)
193 |
194 | ;
195 | ; Square
196 | ;
197 | (defmulti sqr
198 | "Return the square of x."
199 | {:arglists '([x])}
200 | type)
201 |
202 | (defmethod sqr :default
203 | [x]
204 | (ga/* x x))
205 |
206 | ;
207 | ; Approximate equality for use with floating point types
208 | ;
209 | (defn approx=
210 | "Return true if the absolute value of the difference between x and y
211 | is less than eps."
212 | [x y eps]
213 | (gc/< (abs (ga/- x y)) eps))
214 |
--------------------------------------------------------------------------------
/src/test/clojure/clojure/algo/generic/test_collection.clj:
--------------------------------------------------------------------------------
1 | ;; Test routines for clojure.algo.generic.collection
2 |
3 | ;; Copyright (c) Konrad Hinsen, 2011. All rights reserved. The use
4 | ;; and distribution terms for this software are covered by the Eclipse
5 | ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
6 | ;; which can be found in the file epl-v10.html at the root of this
7 | ;; distribution. By using this software in any fashion, you are
8 | ;; agreeing to be bound by the terms of this license. You must not
9 | ;; remove this notice, or any other, from this software.
10 |
11 | (ns clojure.algo.generic.test-collection
12 | (:use [clojure.test :only (deftest is are run-tests)])
13 | (:require [clojure.algo.generic.collection :as gc]))
14 |
15 | ; Define a multiset class. The representation is a map from values to counts.
16 | (defrecord multiset [map])
17 |
18 | (defn mset
19 | [& elements]
20 | (gc/into (new multiset {}) elements))
21 |
22 | ; Implement the collection multimethods.
23 | (defmethod gc/conj multiset
24 | ([ms x]
25 | (let [msmap (:map ms)]
26 | (new multiset (assoc msmap x (inc (get msmap x 0))))))
27 | ([ms x & xs]
28 | (reduce gc/conj (gc/conj ms x) xs)))
29 |
30 | (defmethod gc/empty multiset
31 | [ms]
32 | (new multiset {}))
33 |
34 | (defmethod gc/seq multiset
35 | [ms]
36 | (apply concat (map (fn [[x n]] (repeat n x)) (:map ms))))
37 |
38 | ; Define a sparse vector class. The representation is a map from
39 | ; integer indices to values.
40 | (defrecord sparse-vector [map])
41 |
42 | (defn s-vector
43 | [& values]
44 | (apply gc/conj (new sparse-vector {}) values))
45 |
46 | ; Implement the collection multimethods
47 | (defmethod gc/assoc sparse-vector
48 | [sv key value]
49 | (assert (integer? key))
50 | (assert (not (neg? key)))
51 | (new sparse-vector
52 | (if (nil? value)
53 | (:map sv)
54 | (assoc (:map sv) key value))))
55 |
56 | (defmethod gc/get sparse-vector
57 | ([sv key]
58 | (gc/get sv key nil))
59 | ([sv key default]
60 | (get (:map sv) key default)))
61 |
62 | (defmethod gc/conj sparse-vector
63 | [sv & xs]
64 | (loop [svmap (:map sv)
65 | index (inc (apply max (conj (keys svmap) -1)))
66 | xs xs]
67 | (if (empty? xs)
68 | (new sparse-vector svmap)
69 | (recur (if (nil? (first xs))
70 | svmap
71 | (assoc svmap index (first xs)))
72 | (inc index) (rest xs)))))
73 |
74 | (defmethod gc/empty sparse-vector
75 | [sv]
76 | (new sparse-vector {}))
77 |
78 | (defmethod gc/seq sparse-vector
79 | [sv]
80 | (let [svmap (:map sv)
81 | max-index (apply max (conj (keys svmap) -1))]
82 | (if (neg? max-index)
83 | nil
84 | (for [i (range (inc max-index))] (get svmap i nil)))))
85 |
86 | ; Multiset tests
87 | (deftest multiset-tests
88 | (are [a b] (= a b)
89 | (mset :a :a :b) (mset :a :b :a)
90 | (gc/conj (mset) :a) (mset :a)
91 | (gc/conj (mset) :b :a :b :a) (mset :a :a :b :b)
92 | (gc/empty (mset :a)) (mset)
93 | (gc/seq (mset :a :a :a)) '(:a :a :a)))
94 |
95 | ; Sparse vector tests
96 | (deftest sparse-vector-tests
97 | (are [a b] (= a b)
98 | (gc/empty (s-vector)) (s-vector)
99 | (gc/conj (s-vector 1 2) 3) (s-vector 1 2 3)
100 | (gc/assoc (s-vector 1 2) 2 3) (s-vector 1 2 3)
101 | (gc/assoc (s-vector 1 2) 4 3) (s-vector 1 2 nil nil 3)
102 | (gc/get (s-vector 1 2 3) 1) 2
103 | (gc/seq (gc/assoc (s-vector 1) 3 3)) '(1 nil nil 3)))
104 |
--------------------------------------------------------------------------------
/src/test/clojure/clojure/algo/generic/test_comparison.clj:
--------------------------------------------------------------------------------
1 | ;; Test routines for clojure.algo.generic.comparison
2 |
3 | ;; Copyright (c) Konrad Hinsen, 2011. All rights reserved. The use
4 | ;; and distribution terms for this software are covered by the Eclipse
5 | ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
6 | ;; which can be found in the file epl-v10.html at the root of this
7 | ;; distribution. By using this software in any fashion, you are
8 | ;; agreeing to be bound by the terms of this license. You must not
9 | ;; remove this notice, or any other, from this software.
10 |
11 | (ns clojure.algo.generic.test-comparison
12 | (:use [clojure.test :only (deftest is are run-tests)])
13 | (:require [clojure.algo.generic.comparison :as gc]))
14 |
15 | ; Define a class that wraps a number.
16 | (defrecord my-number [value])
17 | (defn n [value] (new my-number value))
18 |
19 | ; Implement the minimal comparison multimethods.
20 | (defmethod gc/zero? my-number
21 | [x]
22 | (zero? (:value x)))
23 |
24 | (defmethod gc/= [my-number my-number]
25 | [x y]
26 | (= (:value x) (:value y)))
27 |
28 | (defmethod gc/> [my-number my-number]
29 | [x y]
30 | (> (:value x) (:value y)))
31 |
32 | ; Basic tests
33 | (deftest number-comparison
34 | (is (gc/zero? (n 0)))
35 | (is (not (gc/zero? (n 1))))
36 | (is (gc/= (n 2) (n 2)))
37 | (is (gc/not= (n 2) (n 3)))
38 | (is (gc/> (n 3) (n 2)))
39 | (is (gc/>= (n 3) (n 2)))
40 | (is (gc/< (n 2) (n 3)))
41 | (is (gc/<= (n 2) (n 3)))
42 | (is (gc/>= (n 2) (n 2)))
43 | (is (gc/<= (n 2) (n 2))))
44 |
--------------------------------------------------------------------------------
/src/test/clojure/clojure/algo/generic/test_complex.clj:
--------------------------------------------------------------------------------
1 | ;; Test routines for clojure.algo.generic.arithmetic
2 | ;; and clojure.algo.generic.math_functions.
3 |
4 | ;; Copyright (c) Konrad Hinsen, 2011. All rights reserved. The use
5 | ;; and distribution terms for this software are covered by the Eclipse
6 | ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
7 | ;; which can be found in the file epl-v10.html at the root of this
8 | ;; distribution. By using this software in any fashion, you are
9 | ;; agreeing to be bound by the terms of this license. You must not
10 | ;; remove this notice, or any other, from this software.
11 |
12 | (ns clojure.algo.generic.test-complex
13 | (:use [clojure.test :only (deftest is are run-tests)]
14 | [clojure.algo.generic :only (root-type)])
15 | (:require [clojure.algo.generic.arithmetic :as ga]
16 | [clojure.algo.generic.math-functions :as gmf]
17 | [clojure.algo.generic.comparison :as gc]))
18 |
19 | ; Define a basic complex number type
20 | (defrecord complex-number [real imag])
21 |
22 | (defn complex
23 | [real imag]
24 | (new complex-number real imag))
25 |
26 | (defn real
27 | [c]
28 | (:real c))
29 |
30 | (defn imag
31 | [c]
32 | (:imag c))
33 |
34 | ; Minimal implementation of generic.comparison to facilitate testing
35 | (defmethod gc/zero? complex-number
36 | [x]
37 | (and (zero? (real x)) (zero? (imag x))))
38 |
39 | (defmethod gc/= [complex-number complex-number]
40 | [x y]
41 | (and (gc/= (real x) (real y))
42 | (gc/= (imag x) (imag y))))
43 |
44 | (defmethod gc/= [complex-number root-type]
45 | [x y]
46 | (and (gc/zero? (imag x)) (gc/= (real x) y)))
47 |
48 | (defmethod gc/= [root-type complex-number]
49 | [x y]
50 | (and (gc/zero? (imag y)) (gc/= x (real y))))
51 |
52 | ; Arithmetic
53 | (defmethod ga/+ [complex-number complex-number]
54 | [x y]
55 | (complex (ga/+ (real x) (real y)) (ga/+ (imag x) (imag y))))
56 |
57 | (defmethod ga/+ [complex-number root-type]
58 | [x y]
59 | (complex (ga/+ (real x) y) (imag x)))
60 |
61 | (defmethod ga/+ [root-type complex-number]
62 | [x y]
63 | (complex (ga/+ x (real y)) (imag y)))
64 |
65 | (defmethod ga/- complex-number
66 | [x]
67 | (complex (ga/- (real x)) (ga/- (imag x))))
68 |
69 | (defmethod ga/* [complex-number complex-number]
70 | [x y]
71 | (complex (ga/- (ga/* (real x) (real y)) (ga/* (imag x) (imag y)))
72 | (ga/+ (ga/* (real x) (imag y)) (ga/* (imag x) (real y)))))
73 |
74 | (defmethod ga/* [complex-number root-type]
75 | [x y]
76 | (complex (ga/* (real x) y) (ga/* (imag x) y)))
77 |
78 | (defmethod ga/* [root-type complex-number]
79 | [x y]
80 | (complex (ga/* x (real y)) (ga/* x (imag y))))
81 |
82 | (ga/defmethod* ga / complex-number
83 | [x]
84 | (let [rx (real x)
85 | ix (imag x)
86 | den ((ga/qsym ga /) (ga/+ (ga/* rx rx) (ga/* ix ix)))]
87 | (complex (ga/* rx den) (ga/- (ga/* ix den)))))
88 |
89 | ; Math functions
90 | (defmethod gmf/conjugate complex-number
91 | [x]
92 | (complex (real x) (ga/- (imag x))))
93 |
94 | (defmethod gmf/abs complex-number
95 | [x]
96 | (let [r (real x)
97 | i (imag x)]
98 | (gmf/sqrt (ga/+ (ga/* r r) (ga/* i i)))))
99 |
100 | (let [one-half (/ 1 2)
101 | one-eighth (/ 1 8)]
102 | (defmethod gmf/sqrt complex-number
103 | [x]
104 | (let [[r i] (vals x)]
105 | (if (and (gc/zero? r) (gc/zero? i))
106 | 0
107 | (let [; The basic formula would say
108 | ; abs (gmf/sqrt (ga/+ (ga/* r r) (ga/* i i)))
109 | ; p (gmf/sqrt (ga/* one-half (ga/+ abs r)))
110 | ; but the slightly more complicated one below
111 | ; avoids overflow for large r or i.
112 | ar (gmf/abs r)
113 | ai (gmf/abs i)
114 | r8 (ga/* one-eighth ar)
115 | i8 (ga/* one-eighth ai)
116 | abs (gmf/sqrt (ga/+ (ga/* r8 r8) (ga/* i8 i8)))
117 | p (ga/* 2 (gmf/sqrt (ga/+ abs r8)))
118 | q ((ga/qsym ga /) ai (ga/* 2 p))
119 | s (gmf/sgn i)]
120 | (if (gc/< r 0)
121 | (complex q (ga/* s p))
122 | (complex p (ga/* s q))))))))
123 |
124 | (defmethod gmf/exp complex-number
125 | [x]
126 | (let [r (real x)
127 | i (imag x)
128 | exp-r (gmf/exp r)
129 | cos-i (gmf/cos i)
130 | sin-i (gmf/sin i)]
131 | (complex (ga/* exp-r cos-i) (ga/* exp-r sin-i))))
132 |
133 | ; Complex number tests
134 | (deftest complex-addition
135 | (is (gc/= (ga/+ (complex 1 2) (complex 1 2)) (complex 2 4)))
136 | (is (gc/= (ga/+ (complex 1 2) (complex -3 -7)) (complex -2 -5)))
137 | (is (gc/= (ga/+ (complex -3 -7) (complex 1 2)) (complex -2 -5)))
138 | (is (gc/= (ga/+ (complex 1 2) 3) (complex 4 2)))
139 | (is (gc/= (ga/+ 3 (complex 1 2)) (complex 4 2)))
140 | (is (gc/= (ga/+ (complex -3 -7) (complex 1 2)) (complex -2 -5)))
141 | (is (gc/= (ga/+ (complex 1 2) (complex -3 -7)) (complex -2 -5)))
142 | (is (gc/= (ga/+ (complex -3 -7) (complex -3 -7)) (complex -6 -14)))
143 | (is (gc/= (ga/+ (complex -3 -7) -1) (complex -4 -7)))
144 | (is (gc/= (ga/+ -1 (complex -3 -7)) (complex -4 -7)))
145 | (is (gc/= (ga/+ 3 (complex 1 2)) (complex 4 2)))
146 | (is (gc/= (ga/+ (complex 1 2) 3) (complex 4 2)))
147 | (is (gc/= (ga/+ -1 (complex -3 -7)) (complex -4 -7)))
148 | (is (gc/= (ga/+ (complex -3 -7) -1) (complex -4 -7))))
149 |
150 | (deftest complex-subtraction
151 | (is (gc/= (ga/- (complex 1 2) (complex 1 2)) 0))
152 | (is (gc/= (ga/- (complex 1 2) (complex -3 -7)) (complex 4 9)))
153 | (is (gc/= (ga/- (complex -3 -7) (complex 1 2)) (complex -4 -9)))
154 | (is (gc/= (ga/- (complex 1 2) 3) (complex -2 2)))
155 | (is (gc/= (ga/- 3 (complex 1 2)) (complex 2 -2)))
156 | (is (gc/= (ga/- (complex 1 2) -1) (complex 2 2)))
157 | (is (gc/= (ga/- -1 (complex 1 2)) (complex -2 -2)))
158 | (is (gc/= (ga/- (complex -3 -7) (complex 1 2)) (complex -4 -9)))
159 | (is (gc/= (ga/- (complex 1 2) (complex -3 -7)) (complex 4 9)))
160 | (is (gc/= (ga/- (complex -3 -7) (complex -3 -7)) 0))
161 | (is (gc/= (ga/- (complex -3 -7) 3) (complex -6 -7)))
162 | (is (gc/= (ga/- 3 (complex -3 -7)) (complex 6 7)))
163 | (is (gc/= (ga/- (complex -3 -7) -1) (complex -2 -7)))
164 | (is (gc/= (ga/- -1 (complex -3 -7)) (complex 2 7)))
165 | (is (gc/= (ga/- 3 (complex 1 2)) (complex 2 -2)))
166 | (is (gc/= (ga/- (complex 1 2) 3) (complex -2 2)))
167 | (is (gc/= (ga/- 3 (complex -3 -7)) (complex 6 7)))
168 | (is (gc/= (ga/- (complex -3 -7) 3) (complex -6 -7)))
169 | (is (gc/= (ga/- -1 (complex 1 2)) (complex -2 -2)))
170 | (is (gc/= (ga/- (complex 1 2) -1) (complex 2 2)))
171 | (is (gc/= (ga/- -1 (complex -3 -7)) (complex 2 7)))
172 | (is (gc/= (ga/- (complex -3 -7) -1) (complex -2 -7))))
173 |
174 | (deftest complex-multiplication
175 | (is (gc/= (ga/* (complex 1 2) (complex 1 2)) (complex -3 4)))
176 | (is (gc/= (ga/* (complex 1 2) (complex -3 -7)) (complex 11 -13)))
177 | (is (gc/= (ga/* (complex -3 -7) (complex 1 2)) (complex 11 -13)))
178 | (is (gc/= (ga/* (complex 1 2) 3) (complex 3 6)))
179 | (is (gc/= (ga/* 3 (complex 1 2)) (complex 3 6)))
180 | (is (gc/= (ga/* (complex 1 2) -1) (complex -1 -2)))
181 | (is (gc/= (ga/* -1 (complex 1 2)) (complex -1 -2)))
182 | (is (gc/= (ga/* (complex -3 -7) (complex 1 2)) (complex 11 -13)))
183 | (is (gc/= (ga/* (complex 1 2) (complex -3 -7)) (complex 11 -13)))
184 | (is (gc/= (ga/* (complex -3 -7) (complex -3 -7)) (complex -40 42)))
185 | (is (gc/= (ga/* (complex -3 -7) 3) (complex -9 -21)))
186 | (is (gc/= (ga/* 3 (complex -3 -7)) (complex -9 -21)))
187 | (is (gc/= (ga/* (complex -3 -7) -1) (complex 3 7)))
188 | (is (gc/= (ga/* -1 (complex -3 -7)) (complex 3 7)))
189 | (is (gc/= (ga/* 3 (complex 1 2)) (complex 3 6)))
190 | (is (gc/= (ga/* (complex 1 2) 3) (complex 3 6)))
191 | (is (gc/= (ga/* 3 (complex -3 -7)) (complex -9 -21)))
192 | (is (gc/= (ga/* (complex -3 -7) 3) (complex -9 -21)))
193 | (is (gc/= (ga/* -1 (complex 1 2)) (complex -1 -2)))
194 | (is (gc/= (ga/* (complex 1 2) -1) (complex -1 -2)))
195 | (is (gc/= (ga/* -1 (complex -3 -7)) (complex 3 7)))
196 | (is (gc/= (ga/* (complex -3 -7) -1) (complex 3 7))))
197 |
198 | (let [div (ga/qsym ga /)]
199 | (deftest complex-division
200 | (is (gc/= (div (complex 1 2) (complex 1 2)) 1))
201 | (is (gc/= (div (complex 1 2) (complex -3 -7)) (complex -17/58 1/58)))
202 | (is (gc/= (div (complex -3 -7) (complex 1 2)) (complex -17/5 -1/5)))
203 | (is (gc/= (div (complex 1 2) 3) (complex 1/3 2/3)))
204 | (is (gc/= (div 3 (complex 1 2)) (complex 3/5 -6/5)))
205 | (is (gc/= (div (complex 1 2) -1) (complex -1 -2)))
206 | (is (gc/= (div -1 (complex 1 2)) (complex -1/5 2/5)))
207 | (is (gc/= (div (complex -3 -7) (complex 1 2)) (complex -17/5 -1/5)))
208 | (is (gc/= (div (complex 1 2) (complex -3 -7)) (complex -17/58 1/58)))
209 | (is (gc/= (div (complex -3 -7) (complex -3 -7)) 1))
210 | (is (gc/= (div (complex -3 -7) 3) (complex -1 -7/3)))
211 | (is (gc/= (div 3 (complex -3 -7)) (complex -9/58 21/58)))
212 | (is (gc/= (div (complex -3 -7) -1) (complex 3 7)))
213 | (is (gc/= (div -1 (complex -3 -7)) (complex 3/58 -7/58)))
214 | (is (gc/= (div 3 (complex 1 2)) (complex 3/5 -6/5)))
215 | (is (gc/= (div (complex 1 2) 3) (complex 1/3 2/3)))
216 | (is (gc/= (div 3 (complex -3 -7)) (complex -9/58 21/58)))
217 | (is (gc/= (div (complex -3 -7) 3) (complex -1 -7/3)))
218 | (is (gc/= (div -1 (complex 1 2)) (complex -1/5 2/5)))
219 | (is (gc/= (div (complex 1 2) -1) (complex -1 -2)))
220 | (is (gc/= (div -1 (complex -3 -7)) (complex 3/58 -7/58)))
221 | (is (gc/= (div (complex -3 -7) -1) (complex 3 7)))))
222 |
223 | (deftest complex-conjugate
224 | (is (gc/= (gmf/conjugate (complex 1 2)) (complex 1 -2)))
225 | (is (gc/= (gmf/conjugate (complex -3 -7)) (complex -3 7)))
226 | (is (gc/= (gmf/conjugate (complex 0 -2)) (complex 0 2)))
227 | (is (gc/= (gmf/conjugate (complex 0 5)) (complex 0 -5))))
228 |
229 | (deftest complex-abs
230 | (doseq [c [(complex 1 2) (complex -2 3) (complex 4 -2)
231 | (complex -3 -7) (complex 0 -2) (complex 0 5)]]
232 | (is (gmf/approx= (ga/* c (gmf/conjugate c))
233 | (gmf/sqr (gmf/abs c))
234 | 1e-14))))
235 |
236 | (deftest complex-sqrt
237 | (doseq [c [(complex 1 2) (complex -2 3) (complex 4 -2)
238 | (complex -3 -7) (complex 0 -2) (complex 0 5)]]
239 | (let [r (gmf/sqrt c)]
240 | (is (gmf/approx= c (gmf/sqr r) 1e-14))
241 | (is (>= (real r) 0)))))
242 |
243 | (deftest complex-exp
244 | (is (gmf/approx= (gmf/exp (complex 1 2))
245 | (complex -1.1312043837568135 2.4717266720048188)
246 | 1e-14))
247 | (is (gmf/approx= (gmf/exp (complex 2 3))
248 | (complex -7.3151100949011028 1.0427436562359045)
249 | 1e-14))
250 | (is (gmf/approx= (gmf/exp (complex 4 -2))
251 | (complex -22.720847417619233 -49.645957334580565)
252 | 1e-14))
253 | (is (gmf/approx= (gmf/exp (complex 3 -7))
254 | (complex 15.142531566086868 -13.195928586605717)
255 | 1e-14))
256 | (is (gmf/approx= (gmf/exp (complex 0 -2))
257 | (complex -0.41614683654714241 -0.90929742682568171)
258 | 1e-14))
259 | (is (gmf/approx= (gmf/exp (complex 0 5))
260 | (complex 0.2836621854632263 -0.95892427466313845)
261 | 1e-14)))
262 |
--------------------------------------------------------------------------------
/src/test/clojure/clojure/algo/generic/test_functor.clj:
--------------------------------------------------------------------------------
1 | ;; Test routines for clojure.algo.generic.collection
2 |
3 | ;; Copyright (c) Konrad Hinsen, 2011. All rights reserved. The use
4 | ;; and distribution terms for this software are covered by the Eclipse
5 | ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
6 | ;; which can be found in the file epl-v10.html at the root of this
7 | ;; distribution. By using this software in any fashion, you are
8 | ;; agreeing to be bound by the terms of this license. You must not
9 | ;; remove this notice, or any other, from this software.
10 |
11 | (ns clojure.algo.generic.test-functor
12 | (:use [clojure.test :only (deftest is are run-tests)])
13 | (:require [clojure.algo.generic.functor :as gf])
14 | (:require [clojure.algo.generic.collection :as gc]))
15 |
16 | ; Test implementations for CLojure's built-in collections
17 | (deftest builtin-collections
18 | (are [a b] (= a b)
19 | (gf/fmap inc (list 1 2 3)) (list 2 3 4)
20 | (gf/fmap inc [1 2 3]) [2 3 4]
21 | (gf/fmap inc {:A 1 :B 2 :C 3}) {:A 2 :B 3 :C 4}
22 | (gf/fmap inc #{1 2 3}) #{2 3 4}
23 | (gf/fmap inc (lazy-seq [1 2 3])) (list 2 3 4)
24 | (gf/fmap inc (seq [1 2 3])) (list 2 3 4)
25 | (gf/fmap inc (range 3)) (list 1 2 3)
26 | (gf/fmap inc nil) nil))
27 |
28 | ; Test implementation for functions
29 | (deftest functions
30 | (let [f (fn [x] (+ x x))
31 | x [-1 0 1 2]]
32 | (is (= (map (gf/fmap - f) x)
33 | (map (comp - f) x)))))
34 |
35 | ; Futures and delays
36 | (deftest future-test
37 | (is (= 2 @(gf/fmap inc (future 1)))))
38 |
39 | (deftest delay-test
40 | (is (= 2 @(gf/fmap inc (delay 1)))))
41 |
42 | ; Define a multiset class. The representation is a map from values to counts.
43 | (defrecord multiset [map])
44 |
45 | (defn mset
46 | [& elements]
47 | (gc/into (new multiset {}) elements))
48 |
49 | ; Implement the collection multimethods.
50 | (defmethod gc/conj multiset
51 | ([ms x]
52 | (let [msmap (:map ms)]
53 | (new multiset (assoc msmap x (inc (get msmap x 0))))))
54 | ([ms x & xs]
55 | (reduce gc/conj (gc/conj ms x) xs)))
56 |
57 | (defmethod gc/empty multiset
58 | [ms]
59 | (new multiset {}))
60 |
61 | (defmethod gc/seq multiset
62 | [ms]
63 | (apply concat (map (fn [[x n]] (repeat n x)) (:map ms))))
64 |
65 | ; Implement fmap
66 | (defmethod gf/fmap multiset
67 | [f m]
68 | (gc/into (gc/empty m) (map f (gc/seq m))))
69 |
70 | ; Multiset tests
71 | (deftest multiset-tests
72 | (are [a b] (= a b)
73 | (gf/fmap inc (mset 1 2 3)) (mset 2 3 4)))
74 |
75 |
--------------------------------------------------------------------------------