├── LICENSE
├── README.md
├── performance_tests
└── container_comparison
│ ├── Makefile
│ ├── container
│ ├── container.cpp
│ ├── dcontainer
│ ├── dcontainer.cpp
│ ├── scontainer
│ └── scontainer.cpp
├── tensor
├── mapper.hpp
├── tensor.hpp
├── tensor_addition.hpp
├── tensor_container.hpp
├── tensor_dynamic_cpu.hpp
├── tensor_expression_dynamic_cpu.hpp
├── tensor_expression_interface.hpp
├── tensor_expression_static_cpu.hpp
├── tensor_expressions.hpp
├── tensor_operations.hpp
├── tensor_static_cpu.hpp
├── tensor_subtraction.hpp
└── tensor_traits.hpp
└── tests
├── Makefile
├── container_tests.cpp
├── operations_tests.cpp
├── tensor_tests.cpp
├── tests.cpp
└── traits_tests.cpp
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
341 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | *A fast c++ tensor library*
2 |
3 | # Tensor
4 |
5 | Tensor is a c++ tensor expression library. It is designed with both speed and clarity of expression in mind. It it thus intended to provide high levels of performance but allow operations on tensors in the code to appear exactly as they do mathematically.
6 |
7 | [Template metaprogramming](https://en.wikipedia.org/wiki/Template_metaprogramming) is used to 'offload' any work which can be computed at compile time, to the compiler and [expression templates](https://en.wikipedia.org/wiki/Expression_templates) are used to achieve the translation of the mathematically expressed code to high performance code.
8 |
9 | Tests have been written using the [Boost Test library](http://www.boost.org/doc/libs/1_58_0/libs/test/doc/html/index.html) to verify the 'correctness' of all the implemented components. The tests also help to illustrate the usage of the various components of the library.
10 |
11 | The long term goal is to develop something along the lines of the tensor library in the python theano libray,
12 | but with support for any rank tensors with both CPU and GPU functionality.
13 |
14 | # Documentation
15 |
16 | Please see [Tensor Documentation](http://robclu.github.io/tensor/) for documentation and usage examples.
17 |
18 | # Current Status
19 |
20 | Currently the library is CPU only and is single-threaded as the development process has just begun. However, the library will be extended to include GPU functionality (with CUDA and probably also OpenCL) and multi-threading (and therefore multi-core CPU - probably with OpenMP and MPI).
21 |
22 | There is quite a lot of functionality which is working at present, however, the first
23 | iteration of the development used vectors as the data containers. I feel that a lot of performance improvement
24 | can be achieved by using static containers and the properties of the tensor which come with knowing the sizes
25 | of the dimensions when the tensor is created.
26 |
27 | I did some tests with comparing static vs dynamic tensors and the static tensors were up to 20x faster than dynamic tensors, and even faster than ```std::array``` for element access as the static tensors do the mapping using the dimension sizes at compile time.
28 |
29 | I thus decided to completely redesign the interface, allowing a selection between the static and dynamic tensors, as well as a selection between CPU and GPU implementations.
30 |
31 | # Dependencies
32 |
33 | * [nano](https://github.com/robclu/nano) : A template metaprogramming library, is used to offload some of the work to the compiler, for example things like index mapping for slicing and multiplication.
34 | * [boost unit](http://www.boost.org/doc/libs/1_58_0/libs/test/doc/html/index.html) : For the unit testing
35 | component of the library. This is not necessary of you aren't running the tests.
36 |
37 | # Building
38 |
39 | ## Nano
40 |
41 | You can get the nano library from here - [nano](https://github.com/robclu/nano) - it is a header only
42 | library. By default it is installed to ```usr/include```. If you install it somewhere else make sure that it
43 | is on your path so that ```tensor``` can find it.
44 |
45 | ## Boost
46 |
47 | You can get the Boost test library from here - [Boost](http://www.boost.org/) - and follow the [Getting Started Guide](http://www.boost.org/doc/libs/1_59_0/more/getting_started/index.html) to install the libraries.
48 |
49 | __Note:__ You only need the test library, but it is dynamically linked in the tensor tests provided with the ```tensor``` library, so you should install it to allow dynamic linking (i.e install the test library and not just the ```.hpp``` file.)
50 |
51 | ## CUDA
52 |
53 | GPU functionality is not currently implemented so nothing to be done here.
54 |
55 | # Compiling
56 |
57 | Tensor has been tested with the following compilers
58 |
59 | * g++ (4.9.1)
60 | * clang++ (3.6.1)
61 |
62 | Since tensor is (currently) a header-only library, there is nothing to install if you would just like to use it in your own application. However, tests are provided with tensor so ensure that everything is working as expected as well as to provide examples of the usage of tensor.
63 |
64 | To compile the tests, cd into ```tests/```, at which point you are provided with a few options:
65 |
66 | * Make all the tests
67 | * Make an individual tests
68 |
69 | ## All tests
70 |
71 | To make all the tests, simply issue
72 | ```
73 | make all (or make -jN all -- to make in parallel with N processes)
74 | ```
75 |
76 | ## Individual tests
77 |
78 | The following individual test components are provided
79 |
80 | * __tensor__ : tests related to tensors specifically
81 | * __traits__ : tests for the tensor traits
82 | * __container__ : tests for the tensor containers
83 | * __operations__ : tests for the operations (addition, subtraction etc...)
84 |
85 | To make an individual tests, issuse
86 |
87 | ```
88 | make
89 | ```
90 |
91 | with the appropriate test name, for example ```make container```
92 |
93 | ## Cleaning
94 |
95 | To clean the tests, issue
96 |
97 | ```
98 | make clean
99 | ```
100 |
--------------------------------------------------------------------------------
/performance_tests/container_comparison/Makefile:
--------------------------------------------------------------------------------
1 | ########################################################################################
2 | # EXECUTABLE NAME #
3 | ########################################################################################
4 |
5 | EXE_SCONT := scontainer
6 | EXE_DCONT := dcontainer
7 | EXE_CONT := container
8 |
9 | ########################################################################################
10 | # INPUT FILES #
11 | ########################################################################################
12 |
13 | INPUTS :=
14 | OBJS :=
15 |
16 | ########################################################################################
17 | # COMPILERS #
18 | # #
19 | # NOTE: Compiling with cuda because GPU support will be added #
20 | ########################################################################################
21 |
22 | CXX := g++
23 |
24 | ########################################################################################
25 | # INCLUDE DIRECTORIES #
26 | ########################################################################################
27 |
28 | CXX_INC :=
29 |
30 | ########################################################################################
31 | # LIBRARIES #
32 | ########################################################################################
33 |
34 | CXX_LIBS :=
35 | CXX_LDIR :=
36 |
37 | ########################################################################################
38 | # COMPILER FLAGS #
39 | # #
40 | # NOTE: To enable compiler warnings, remove -w and replace with : #
41 | # --compiler-options -Wall #
42 | ########################################################################################
43 |
44 | CXX_FLAGS := -std=c++11 -w -O3
45 |
46 | ########################################################################################
47 | # TARGET RULES #
48 | #######################################################################################
49 |
50 | .PHONY: scont scont_asm dcont dcont_asm cont clean
51 |
52 | scont: build_and_run_scont
53 | dcont: build_and_run_dcont
54 | cont: build_and_run_cont
55 |
56 | build_and_run_scont: build_scont
57 | rm -rf *.o
58 | ./$(EXE_SCONT)
59 |
60 | scontainer.o: scontainer.cpp
61 | $(CXX) $(CXX_INC) $(CXX_FLAGS) -o $@ -c $<
62 |
63 | build_scont: scontainer.o
64 | $(CXX) -o $(EXE_SCONT) $+ $(CXX_LDIR) $(CXX_LIBS)
65 |
66 | scontainer.s: scontainer.cpp
67 | $(CXX) $(CXX_INC) $(CXX_FLAGS) -o $@ -c $<
68 |
69 | scont_asm: CXX_FLAGS += -S -g -fverbose-asm -masm=intel -O3
70 | scont_asm: scontainer.s
71 | as -adhln scontainer.s > scontainer.lst
72 |
73 | build_and_run_dcont: build_dcont
74 | rm -rf *.o
75 | ./$(EXE_DCONT)
76 |
77 | dcontainer.o: dcontainer.cpp
78 | $(CXX) $(CXX_INC) $(CXX_FLAGS) -o $@ -c $<
79 |
80 | build_dcont: dcontainer.o
81 | $(CXX) -o $(EXE_DCONT) $+ $(CXX_LDIR) $(CXX_LIBS)
82 |
83 | dcontainer.s: dcontainer.cpp
84 | $(CXX) $(CXX_INC) $(CXX_FLAGS) -o $@ -c $<
85 |
86 | dcont_asm: CXX_FLAGS += -S -g -fverbose-asm -masm=intel -O3
87 | dcont_asm: dcontainer.s
88 | as -adhln dcontainer.s > dcontainer.lst
89 |
90 | build_and_run_cont: build_cont
91 | rm -rf *.o
92 | ./$(EXE_CONT)
93 |
94 | container.o: container.cpp
95 | $(CXX) $(CXX_INC) $(CXX_FLAGS) -o $@ -c $<
96 |
97 | build_cont: container.o
98 | $(CXX) -o $(EXE_CONT) $+ $(CXX_LDIR) $(CXX_LIBS)
99 |
100 | clean:
101 | rm -rf *.o
102 | rm -rf *.s
103 | rm -rf *.lst
104 | rm -rf $(EXE_SCONT)
105 | rm -rf $(EXE_DCONT)
106 | rm -rf $(EXE_CONT)
107 |
108 |
--------------------------------------------------------------------------------
/performance_tests/container_comparison/container:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robclu/tensor/52da3491984b60cc2559fb4cc9a4f7f2bcfc396c/performance_tests/container_comparison/container
--------------------------------------------------------------------------------
/performance_tests/container_comparison/container.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using std::array;
5 | using std::cout;
6 |
7 | constexpr size_t D1 = 200;
8 | constexpr size_t D2 = 3000;
9 |
10 | int main(int argc, char** argv)
11 | {
12 | array container;
13 | size_t offset = 0;
14 |
15 | for (size_t i = 0; i < D1; ++i)
16 | for (size_t j = 0; j < D2; ++j)
17 | offset = container[i * D1 + j];
18 |
19 | std::cout << offset;
20 | }
21 |
--------------------------------------------------------------------------------
/performance_tests/container_comparison/dcontainer:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robclu/tensor/52da3491984b60cc2559fb4cc9a4f7f2bcfc396c/performance_tests/container_comparison/dcontainer
--------------------------------------------------------------------------------
/performance_tests/container_comparison/dcontainer.cpp:
--------------------------------------------------------------------------------
1 | #include "../../tensor/container_mapper.hpp"
2 | #include
3 |
4 | constexpr size_t D1 = 200;
5 | constexpr size_t D2 = 3000;
6 | constexpr size_t D3 = 7;
7 | constexpr size_t D4 = 2;
8 | constexpr size_t D5 = 2;
9 | constexpr size_t D6 = 12;
10 |
11 | int main(int argc, char** argv)
12 | {
13 |
14 | std::vector dim_sizes{ D1, D2, D3, D4, D5, D6 };
15 | size_t offset = 0;
16 |
17 | for (size_t i = 0; i < D1; ++i)
18 | for (size_t j = 0; j < D2; ++j)
19 | offset = ftl::dynamic_mapper::indices_to_index(dim_sizes, i, j, 2, 0, 1, 8);
20 |
21 | std::cout << offset;
22 | }
23 |
--------------------------------------------------------------------------------
/performance_tests/container_comparison/scontainer:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robclu/tensor/52da3491984b60cc2559fb4cc9a4f7f2bcfc396c/performance_tests/container_comparison/scontainer
--------------------------------------------------------------------------------
/performance_tests/container_comparison/scontainer.cpp:
--------------------------------------------------------------------------------
1 | #include "../../tensor/container_mapper.hpp"
2 | #include "../../tensor/tensor.h"
3 |
4 | constexpr size_t D1 = 200;
5 | constexpr size_t D2 = 3000;
6 | constexpr size_t D3 = 7;
7 | constexpr size_t D4 = 20;
8 | constexpr size_t D5 = 2;
9 | constexpr size_t D6 = 12;
10 |
11 | int main(int argc, char** argv)
12 | {
13 | // Define sype for static tensor
14 | using static_type = ftl::stensor; // Static tensor type
15 | using dim_sizes = static_type::data_container::dimension_sizes; // dim sizes of static tensor
16 |
17 | static_type s;
18 |
19 | size_t offset = 0;
20 |
21 | for (size_t i = 0; i < D1; ++i)
22 | for (size_t j = 0; j < D2; ++j)
23 | offset = ftl::static_mapper::indices_to_index(i, j, 2, 0, 1, 8);
24 |
25 | std::cout << offset;
26 | }
27 |
--------------------------------------------------------------------------------
/tensor/mapper.hpp:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------
2 | /// @file Header file for mapper related classes and variables for mapping linear indices to multiple
3 | /// dimensions and from mapping multiple dimensions to a linear index etc for both static and dynamic
4 | /// containers
5 | // ----------------------------------------------------------------------------------------------------------
6 |
7 | /*
8 | * ----------------------------------------------------------------------------------------------------------
9 | * Header file for mapper class
10 | * Copyright (C) 2015 Rob Clucas robclu1818@gmail.com
11 | *
12 | * This program is free software; you can redistribute it and/or modify
13 | * it under the terms of the GNU General Public License as published
14 | * by the Free Software Foundation; either version 2 of the License, or
15 | * (at your option) any later version.
16 | *
17 | * This program is distributed in the hope that it will be useful,
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | * GNU General Public License for more details.
21 | *
22 | * You should have received a copy of the GNU General Public License along
23 | * with this program; if not, write to the Free Software Foundation,
24 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 | * ----------------------------------------------------------------------------------------------------------
26 | */
27 |
28 | #ifndef FTL_MAPPER_HPP
29 | #define FTL_MAPPER_HPP
30 |
31 | #include
32 |
33 | #include
34 | #include
35 | #include
36 |
37 | namespace ftl {
38 |
39 | namespace detail {
40 |
41 | // ----------------------------------------------------------------------------------------------------------
42 | /// @struct MapToIndexStatic
43 | /// @brief Takes a list of indices and a list of dimension sizes, and determines the offset of an
44 | /// element given by the indices, in contiguous memory
45 | /// @tparam DimSizes The sizes of each of the dimensions
46 | /// @tparam Indices The value of the element in each of the indices
47 | // ----------------------------------------------------------------------------------------------------------
48 | template
49 | struct MapToIndexStatic;
50 |
51 | // Recursive case
52 | template
53 | struct MapToIndexStatic
54 | {
55 | // On each iteration the product of the size of all previous dimensions must be calculated
56 | // to determine the memory offset of this dimension, so determine the stopping index
57 | using end_index = typename std::conditional<
58 | DimSizes::size - sizeof...(IR) == 1 ,
59 | typename nano::size_t<0> ,
60 | typename nano::size_t>::type;
61 |
62 | // The product sum of the previous dimensions (previous iterations) so if we are on iteration
63 | // 3 then this is the product of the size of dimension 0 and 1
64 | static constexpr size_t dim_product_sum = nano::accumulate::result;
65 |
66 | // The offset calculation
67 | static constexpr size_t offset(size_t current_offset, IF&& index_first, IR&&... indices_rest)
68 | {
69 | // Recursively call until the terminating case
70 | // If first iteration use index_first as offset
71 | // if other iteration, add mult with prev products
72 | return DimSizes::size - sizeof...(IR) == 1
73 | ? MapToIndexStatic::offset(current_offset + index_first ,
74 | std::forward(indices_rest)... )
75 | : MapToIndexStatic::offset(current_offset + index_first * dim_product_sum,
76 | std::forward(indices_rest)... );
77 | }
78 | };
79 |
80 | // Terminating (base) case
81 | template
82 | struct MapToIndexStatic
83 | {
84 | // Just need to return the result here
85 | static constexpr size_t offset(size_t current_offset) { return current_offset; }
86 | };
87 |
88 | // Dynamic implementation
89 | template
90 | size_t MapToIndexDynamic(const Container& dim_sizes ,
91 | size_t current_offset )
92 | {
93 | return current_offset;
94 | }
95 |
96 | template
97 | size_t MapToIndexDynamic(const Container& dim_sizes ,
98 | size_t current_offset ,
99 | IF index_first ,
100 | IR... indices_rest )
101 | {
102 | size_t num_indices = sizeof...(IR);
103 | current_offset += std::accumulate(dim_sizes.begin() ,
104 | dim_sizes.end() - num_indices - 1 ,
105 | 1 ,
106 | std::multiplies() ) * index_first;
107 | // Keep iterating
108 | return MapToIndexDynamic(dim_sizes, current_offset, indices_rest...);
109 | }
110 |
111 | } // End namespace detail
112 |
113 | // ----------------------------------------------------------------------------------------------------------
114 | /// @struct StaticMapper
115 | /// @brief Interface which provides static mapping (uses TMP to determine some of the mapping variables
116 | /// at compile time for improved performance) from indices to a single offset index and from an
117 | /// index offset to a list of indices
118 | // ----------------------------------------------------------------------------------------------------------
119 | struct StaticMapper {
120 |
121 | // ----------------------------------------------------------------------------------------------------------
122 | /// @brief Maps any number of indices which represent the location of an index in a multi-dimensional
123 | /// space, to a singe index offset in the contiguous memory which is representing that
124 | /// multi-dimensional space
125 | /// @param[in] index_first The index of the element in the first dimension
126 | /// @param[in] indices_rest The indices of the element in the other dimensions
127 | /// @tparam DimSizes The list of dimension sizes for the multi-dimensional space
128 | /// @tparam IF The type of index_first
129 | /// @tparam IR The types of indices_rest
130 | // ----------------------------------------------------------------------------------------------------------
131 | template
132 | static constexpr size_t indices_to_index(IF&& index_first, IR&&... indices_rest)
133 | {
134 | return detail::MapToIndexStatic::offset(0 ,
135 | std::forward(index_first) ,
136 | std::forward(indices_rest)... );
137 | }
138 |
139 | };
140 |
141 | struct DynamicMapper {
142 |
143 | template
144 | static size_t indices_to_index(const Container& dim_sizes ,
145 | IF index_first ,
146 | IR... indices_rest)
147 | {
148 | return detail::MapToIndexDynamic<1>(dim_sizes, index_first, indices_rest...);
149 | }
150 |
151 | };
152 |
153 | } // End namespace ftl
154 | #endif // FTL_MAPPER_HPP
155 |
--------------------------------------------------------------------------------
/tensor/tensor.hpp:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------
2 | /// @file Header file for tensor interface for tensor library.
3 | // ----------------------------------------------------------------------------------------------------------
4 |
5 | /*
6 | * ----------------------------------------------------------------------------------------------------------
7 | * Tensor is free software; you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published
9 | * by the Free Software Foundation; either version 2 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * Tensor is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License along
18 | * with tensor; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 | * ----------------------------------------------------------------------------------------------------------
21 | */
22 |
23 | #ifndef FTL_TENSOR_HPP
24 | #define FTL_TENSOR_HPP
25 |
26 | //#include "tensor_expressions.hpp"
27 | #include "tensor_dynamic_cpu.hpp"
28 | #include "tensor_static_cpu.hpp"
29 |
30 | namespace ftl {
31 |
32 | // Define a type alias for a general tensor that will 'choose' the specialization
33 | template
34 | using Tensor = TensorInterface>;
35 |
36 | } // End namespace ftl
37 | #endif // FTL_TENSOR_INTERFACE_HPP
38 |
--------------------------------------------------------------------------------
/tensor/tensor_addition.hpp:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------
2 | /// @file Header file for tensor addition for tensor library.
3 | // ----------------------------------------------------------------------------------------------------------
4 |
5 | /*
6 | * ----------------------------------------------------------------------------------------------------------
7 | * Tensor is free software; you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published
9 | * by the Free Software Foundation; either version 2 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * Tensor is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License along
18 | * with tensor; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 | * ----------------------------------------------------------------------------------------------------------
21 | */
22 |
23 | #ifndef FTL_TENSOR_ADDITION_HPP
24 | #define FTL_TENSOR_ADDITION_HPP
25 |
26 | #include "tensor_expressions.hpp"
27 |
28 | namespace ftl {
29 |
30 | // ----------------------------------------------------------------------------------------------------------
31 | /// @class TensorAddition
32 | /// @brief Expression class for calculating the addition of two tensors.
33 | /// @tparam E1 The first expression for addition
34 | /// @tparam E2 The second expression for addition
35 | /// @tparam T1 The traits of the first expression
36 | /// @tparam T2 The traits if the second expression
37 | // ----------------------------------------------------------------------------------------------------------
38 | template
39 | class TensorAddition : public TensorExpression, T1> {
40 | public:
41 | using traits = T1;
42 | using dim_container = typename traits::dim_container;
43 | using size_type = typename traits::size_type;
44 | using data_type = typename traits::data_type;
45 | private:
46 | E1 const& _x; //!< First expression for addition
47 | E2 const& _y; //!< Second expression for addition
48 | public:
49 | // ------------------------------------------------------------------------------------------------------
50 | /// @brief Sets the expressions for addition and checks that they have the same ranks and dimension
51 | /// @param[in] x The first expression for addition.
52 | /// @param[in] y The second expression for addition
53 | // ------------------------------------------------------------------------------------------------------
54 | TensorAddition(TensorExpression const& x, TensorExpression const& y);
55 |
56 | // ------------------------------------------------------------------------------------------------------
57 | /// @brief Gets the sizes of the all the dimensions of the expression.
58 | /// @return A constant reference to the dimension size vector of the expression
59 | // ------------------------------------------------------------------------------------------------------
60 | inline const dim_container& dim_sizes() const { return _x.dim_sizes(); }
61 |
62 | // ------------------------------------------------------------------------------------------------------
63 | /// @brief Returns the size of the expression.
64 | /// @return The size of the tensor_addition.
65 | // ------------------------------------------------------------------------------------------------------
66 | inline const size_type size() const { return _x.size(); }
67 |
68 | // ------------------------------------------------------------------------------------------------------
69 | /// @brief Returns the size of the expression.
70 | /// @return The size of the tensor_addition.
71 | // ------------------------------------------------------------------------------------------------------
72 | inline const size_type rank() const { return _x.rank(); }
73 |
74 | // ------------------------------------------------------------------------------------------------------
75 | /// @brief Adds two elements (one from each Tensor) from the tensor expression data.
76 | /// @param[in] i The element in the expression which must be fetched.
77 | /// @return The result of the subtraction of the Tensors.
78 | // ------------------------------------------------------------------------------------------------------
79 | inline data_type operator[](size_type i) const { return _x[i] + _y[i]; }
80 | };
81 |
82 | // ------------------------------------- ADDITION IMPLEMENTATIONS -------------------------------------------
83 |
84 | template
85 | TensorAddition::TensorAddition(const TensorExpression& x,
86 | const TensorExpression& y)
87 | : _x(x), _y(y)
88 | {
89 | int i = 0;
90 | while (x.dim_sizes()[i] == y.dim_sizes()[i]) ++i; // Check equality of dimension sizes
91 |
92 | // TODO: Add error throwing
93 | // Check that the ranks are equal
94 | if (x.rank() != y.rank() || i != x.rank()) ;
95 | // Throw error here
96 | }
97 |
98 | } // End namespace ftl
99 | #endif // FTL_TENSOR_ADDITION_HPP
100 |
--------------------------------------------------------------------------------
/tensor/tensor_container.hpp:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------
2 | /// @file Header file for TensorConainer class to allow both static and dynamic containers
3 | // ----------------------------------------------------------------------------------------------------------
4 |
5 | /*
6 | * ----------------------------------------------------------------------------------------------------------
7 | * Tensor is free software; you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published
9 | * by the Free Software Foundation; either version 2 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * Tensor is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License along
18 | * with tensor; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 | * ----------------------------------------------------------------------------------------------------------
21 | */
22 |
23 | #ifndef FTL_TENSOR_CONTAINER_HPP
24 | #define FTL_TENSOR_CONTAINER_HPP
25 |
26 | #include
27 |
28 | #include
29 | #include
30 |
31 | namespace ftl {
32 |
33 | // ----------------------------------------------------------------------------------------------------------
34 | /// @struct TensorContainer
35 | /// @brief Container for tensor data depending on if the tensor is static (dimension sizes, and hence the
36 | /// total number of elements, are known at compile time -- uses std::array) or dynamic (dimension
37 | /// sizes are not known at compile time -- uses std::vector).
38 | /// @tparam Dtype The type of data used by the tensor
39 | /// @tparam Sizes The sizes of the dimensions (optional)
40 | // ----------------------------------------------------------------------------------------------------------
41 | template
42 | class TensorContainer;
43 |
44 | // Specialize for static containers -- for when the sizes of the dimensions are given at compile-time
45 | template
46 | class TensorContainer {
47 | public:
48 | // ---------------------------------------- ALIAS'S -----------------------------------------------------
49 | using data_type = Dtype;
50 | using dimension_sizes = nano::list, nano::size_t...>;
51 | using dimension_product = nano::multiplies;
52 | using data_container = std::array;
53 | using dim_container = typename nano::runtime_converter::array_type;
54 | using size_type = typename data_container::size_type;
55 | using iterator = typename data_container::iterator;
56 | // ------------------------------------------------------------------------------------------------------
57 |
58 | // ------------------------------------------------------------------------------------------------------
59 | /// @brief Default constructor
60 | // ------------------------------------------------------------------------------------------------------
61 | TensorContainer() {}
62 |
63 | // ------------------------------------------------------------------------------------------------------
64 | /// @brief Contructor when given an array with the data for the container
65 | /// @param[in] data The data to use to initalize the container data with
66 | // ------------------------------------------------------------------------------------------------------
67 | constexpr TensorContainer(data_container& data)
68 | : _data(data) {}
69 |
70 | // ------------------------------------------------------------------------------------------------------
71 | /// @brief Move constructor for when the data is given as a literal list
72 | /// @param[in] values The first value in the literal list
73 | /// @tparam TR The type of the rest of the parameters
74 | // ------------------------------------------------------------------------------------------------------
75 | template
76 | constexpr TensorContainer(TR&&... values)
77 | : _data{{std::forward(values)...}} {}
78 |
79 | // ------------------------------------------------------------------------------------------------------
80 | /// @brief Gets the size (total number of elements) in the container
81 | /// @return The size of the container
82 | // ------------------------------------------------------------------------------------------------------
83 | constexpr size_t size() const { return dimension_product::result; }
84 |
85 | // ------------------------------------------------------------------------------------------------------
86 | /// @brief Gets an element from the container
87 | /// @param[in] i The index of the element in the container
88 | /// @return A reference to the element at the index i in the container
89 | // ------------------------------------------------------------------------------------------------------
90 | inline data_type& operator[](size_t i) { return _data[i]; }
91 |
92 | // ------------------------------------------------------------------------------------------------------
93 | /// @brief Gets an element from the container
94 | /// @param[in] i The index of the element in the container
95 | /// @return A reference to the element at the index i in the container
96 | // ------------------------------------------------------------------------------------------------------
97 | inline const data_type& operator[](size_t i) const { return _data[i]; }
98 |
99 | // ------------------------------------------------------------------------------------------------------
100 | /// @brief Returns an iterator to the first element of the container
101 | /// @return An iterator to the first element of the container
102 | // ------------------------------------------------------------------------------------------------------
103 | iterator begin() { return _data.begin(); }
104 |
105 | // ------------------------------------------------------------------------------------------------------
106 | /// @brief Returns an iterator to the element following the last element
107 | /// @return An iterator to the element following the last element
108 | // ------------------------------------------------------------------------------------------------------
109 | iterator end() { return _data.end(); }
110 | private:
111 | data_container _data; //!< Static data for a tensor
112 | };
113 |
114 | // Specialization for dynamic container which the dimension sizes
115 | // (and hence the number of elements) are not known at compile time
116 | template
117 | class TensorContainer {
118 | public:
119 | // ----------------------------------------- ALIAS'S ----------------------------------------------------
120 | using data_type = Dtype;
121 | using data_container = std::vector;
122 | using size_type = typename data_container::size_type;
123 | using dim_container = std::vector;
124 | using iterator = typename data_container::iterator;
125 | // ------------------------------------------------------------------------------------------------------
126 |
127 | // ------------------------------------------------------------------------------------------------------
128 | /// @brief Default constructor
129 | // ------------------------------------------------------------------------------------------------------
130 | TensorContainer() : _size(0), _data(0) {}
131 |
132 | // ------------------------------------------------------------------------------------------------------
133 | /// @brief Contructor when given an array with the data for the container
134 | /// @param[in] data The data to use to initalize the container data with
135 | // ------------------------------------------------------------------------------------------------------
136 | TensorContainer(data_container& data)
137 | : _size(data.size()), _data(data){}
138 |
139 | // ------------------------------------------------------------------------------------------------------
140 | /// @brief Gets the size (total number of elements) in the container
141 | /// @return The size of the container
142 | // ------------------------------------------------------------------------------------------------------
143 | inline size_t size() const { return _size; }
144 |
145 | // ------------------------------------------------------------------------------------------------------
146 | /// @brief Gets an element from the container
147 | /// @param[in] i The index of the element in the container
148 | /// @return A reference to the element at the index i in the container
149 | // ------------------------------------------------------------------------------------------------------
150 | inline data_type& operator[](size_t i) { return _data[i]; }
151 |
152 | // ------------------------------------------------------------------------------------------------------
153 | /// @brief Gets an element from the container
154 | /// @param[in] i The index of the element in the container
155 | /// @return A reference to the element at the index i in the container
156 | // ------------------------------------------------------------------------------------------------------
157 | inline const data_type& operator[](size_t i) const { return _data[i]; }
158 |
159 | // ------------------------------------------------------------------------------------------------------
160 | /// @brief Returns an iterator to the first element of the container
161 | /// @return An iterator to the first element of the container
162 | // ------------------------------------------------------------------------------------------------------
163 | iterator begin() { return _data.begin(); }
164 |
165 | // ------------------------------------------------------------------------------------------------------
166 | /// @brief Returns an iterator to the element following the last element
167 | /// @return An iterator to the element following the last element
168 | // ------------------------------------------------------------------------------------------------------
169 | iterator end() { return _data.end(); }
170 | private:
171 | data_container _data; //!< Dynamic data container for a tensor
172 | size_t _size; //!< Number of elements in the container
173 | };
174 |
175 | } // End namespace ftl
176 |
177 | #endif // FTL_TENSOR_CONTAINER_HPP
178 |
--------------------------------------------------------------------------------
/tensor/tensor_dynamic_cpu.hpp:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------
2 | /// @file Header file for tensor specialization with a dynamic container using the cpu.
3 | // ----------------------------------------------------------------------------------------------------------
4 |
5 | /*
6 | * ----------------------------------------------------------------------------------------------------------
7 | * Tensor is free software; you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published
9 | * by the Free Software Foundation; either version 2 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * Tensor is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License along
18 | * with Tensor; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 | * ----------------------------------------------------------------------------------------------------------
21 | */
22 |
23 | #ifndef FTL_TENSOR_DYNAMIC_CPU_HPP
24 | #define FTL_TENSOR_DYNAMIC_CPU_HPP
25 |
26 | #include "mapper.hpp"
27 | #include "tensor_expression_dynamic_cpu.hpp" // NOTE: Only including expression specialization for
28 | // dynamic cpu implementation -- all specializations
29 | // are provided by tensor_expressions.hpp
30 |
31 | #include
32 | #include
33 |
34 | // NOTE : Using long template names results in extremely bulky code, so the following abbreviations are
35 | // used to reduve the bulk for template parameters:
36 | // - DT = Dtype = data type
37 | // - SF = SizeFirst = size of first dimension
38 | // - SR = SizeRest = size of other dimensions
39 | // - CPU = CPU = CPU device used for computation
40 | namespace ftl {
41 |
42 | // Forward declaration of TensorInterface so that we can provide the specialization
43 | template
44 | class TensorInterface;
45 |
46 | // Type alias for dynamic cpu tensor to make the code more readable
47 | template
48 | using DynamicTensorCpu = TensorInterface>;
49 |
50 | // Specialization for a tensor using a dynamic container and CPU devices
51 | template
52 | class TensorInterface> : public TensorExpression ,
53 | TensorTraits> {
54 | public:
55 | // ---------------------------------------- ALIAS'S -----------------------------------------------------
56 | using traits = TensorTraits;
57 | using container_type = typename traits::container_type;
58 | using data_container = typename traits::data_container;
59 | using dim_container = typename traits::dim_container;
60 | using data_type = typename traits::data_type;
61 | using size_type = typename traits::size_type;
62 | // ------------------------------------------------------------------------------------------------------
63 |
64 | // ------------------------------------------------------------------------------------------------------
65 | /// @brief Default constructor - sets the data to have no elements, the rank to the specified rank
66 | // ------------------------------------------------------------------------------------------------------
67 | explicit TensorInterface(size_type rank) : _data(0), _rank(rank), _dim_sizes(rank) {}
68 |
69 | // ------------------------------------------------------------------------------------------------------
70 | /// @brief Constructor using vectors to set the dimension sizes and the data of the tensor. Moves the
71 | /// data if the data are passed as rvalue references.
72 | /// @param dim_sizes The sizes of each of the dimensions for the tensor.
73 | /// @param data The data for the tensor.
74 | // ------------------------------------------------------------------------------------------------------
75 | TensorInterface(dim_container& dim_sizes, data_container& data);
76 |
77 | // ------------------------------------------------------------------------------------------------------
78 | /// @brief Constructor using vectors to set the dimension sizes and the data of the tensor. Moves the
79 | /// data if the data are passed as rvalue references.
80 | /// @param dim_sizes The sizes of each of the dimensions for the tensor.
81 | /// @param data The data for the tensor.
82 | // ------------------------------------------------------------------------------------------------------
83 | TensorInterface(dim_container&& dim_sizes, data_container&& data);
84 |
85 | // ------------------------------------------------------------------------------------------------------
86 | /// @brief Constructor using an initializer list - sets the size of each of the dimensions to the
87 | /// values in the intializer_list and the total number of elements equal to the product of
88 | /// the dimension sizes.
89 | /// @param[in] dim_sizes The list of dimension sizes where the nth element in the list sets the size
90 | /// of the nth dimension of the tensor.
91 | // ------------------------------------------------------------------------------------------------------
92 | TensorInterface(std::initializer_list dim_sizes);
93 |
94 | // ------------------------------------------------------------------------------------------------------
95 | /// @brief Constructor for creation from a tensor expression -- this is only used for simple
96 | /// expressions (which do not modify the rank and/or dimension sizes) -- such as addition
97 | /// and subtraction. Rank modifying expressions-- such as multiplication and slicing -- have
98 | /// specialized constructors (to be implemented).
99 | /// @param[in] expression The expression instance to create the static tensor from
100 | /// @tparam Expression The type of the expressionA
101 | /// @tparam Traits The tensor traits of the expression
102 | // ------------------------------------------------------------------------------------------------------
103 | template
104 | TensorInterface(const TensorExpression& expression);
105 |
106 | // ------------------------------------------------------------------------------------------------------
107 | /// @brief Gets the rank (number of dimensions) of the tensor.
108 | /// @return The rank (number of dimensions) of the tensor.
109 | // ------------------------------------------------------------------------------------------------------
110 | inline size_type rank() const { return _rank; }
111 |
112 | // ------------------------------------------------------------------------------------------------------
113 | /// @brief Gets the size (total number of elements) of the tensor
114 | /// @return The total number of elements in the tensor.
115 | // ------------------------------------------------------------------------------------------------------
116 | inline size_type size() const { return _data.size(); }
117 |
118 | // NOTE: need to add out of range exception here too
119 | // ------------------------------------------------------------------------------------------------------
120 | /// @brief Gets the size of a specific dimension of the tensor, if the requested dimension is
121 | /// invalid then 0 is returned.
122 | /// @param[in] dim The dimension for which the size must be returned.
123 | /// @return The number of elements in the requested dimension, if the dimension is a valid dimension
124 | /// for the tensor, otherwise 0 is returned.
125 | // ------------------------------------------------------------------------------------------------------
126 | inline size_t size(const int dim) const { return dim < _rank ? _dim_sizes[dim] : 0; }
127 |
128 | // ------------------------------------------------------------------------------------------------------
129 | /// @brief Gets a vector holding the size of each dimension of the tensor.
130 | /// @return A vector holding the size of each dimension of the tensor.
131 | // ------------------------------------------------------------------------------------------------------
132 | const dim_container& dim_sizes() const { return _dim_sizes; }
133 |
134 | // ------------------------------------------------------------------------------------------------------
135 | /// @brief Gets the tensor data.
136 | /// @return The data for the tensor.
137 | // ------------------------------------------------------------------------------------------------------
138 | const data_container& data() const { return _data; }
139 |
140 | // ------------------------------------------------------------------------------------------------------
141 | /// @brief Initializes each element of the tensor between a range using a uniform ditribution
142 | /// @param[in] min The minimum value of an element after the initialization
143 | /// @param[in] max The max value of an element after the initialization
144 | // ------------------------------------------------------------------------------------------------------
145 | void initialize(const data_type min, const data_type max);
146 |
147 | // ------------------------------------------------------------------------------------------------------
148 | /// @brief Gets the element at position i in the tensor's data vector, by refernce
149 | /// @param[in] i The index of the element to access.
150 | /// @return The element at position i in the tensor's data vecor.
151 | // ------------------------------------------------------------------------------------------------------
152 | inline data_type& operator[](size_type i) { return _data[i]; }
153 |
154 | // ------------------------------------------------------------------------------------------------------
155 | /// @brief Gets the element at position i in the tensor's data vector, by value.
156 | /// @param[in] i The index of the element to access.
157 | /// @return The element at position i in the tensor's data vector.
158 | // ------------------------------------------------------------------------------------------------------
159 | inline const data_type& operator[](size_type i) const { return _data[i]; }
160 |
161 | // ------------------------------------------------------------------------------------------------------
162 | /// @brief Gets the element at a given index for each dimension of a tensor -- there is no bound
163 | /// checking as bound checking implementations will be provided through .at()
164 | /// @param[in] index_dim_one The index of the element in dimension 1
165 | /// @param[in] index_dim_other The index of the element in the other dimensions
166 | /// @tparam IF The type of the first index parameter
167 | /// @tparam IR The types of the rest of the index parameters
168 | /// @return A reference to the element at the position given by the indices
169 | // ------------------------------------------------------------------------------------------------------
170 | template
171 | DT& operator()(IF index_dim_one, IR... index_dim_other);
172 |
173 | // ------------------------------------------------------------------------------------------------------
174 | /// @brief Gets the element at a given index for each dimension of a tensor -- there is no bound
175 | /// checking as bound checking implementations will be provided through .at()
176 | /// @param[in] index_dim_one The index of the element in dimension 1
177 | /// @param[in] index_dim_other The index of the element in the other dimensions
178 | /// @tparam IF The type of the first index parameter
179 | /// @tparam IR The types of the rest of the index parameters
180 | /// @return The value of the element at the position given by the indices
181 | // ------------------------------------------------------------------------------------------------------
182 | template
183 | DT operator()(IF index_dim_one, IR... index_dim_other) const;
184 | private:
185 | data_container _data; //!< Data for the tensor
186 | dim_container _dim_sizes; //!< Sizes of the dimensions for the tensor
187 | size_type _rank; //!< The rank (number of dimensions) in the tensor
188 | };
189 |
190 | // ------------------------------------------- IMPLEMENTATIONS ----------------------------------------------
191 |
192 | // ----------------------------------------------- PUBLIC ---------------------------------------------------
193 |
194 | template
195 | TensorInterface>::TensorInterface(std::initializer_list dim_sizes)
196 | : _data(std::accumulate(dim_sizes.begin(), dim_sizes.end(), 1, std::multiplies())),
197 | _rank(dim_sizes.size())
198 | {
199 | for (auto& element : dim_sizes) _dim_sizes.push_back(element);
200 | }
201 |
202 | template
203 | TensorInterface>::TensorInterface(dim_container& dim_sizes, data_container& data)
204 | : _data(data), _rank(dim_sizes.size()), _dim_sizes(dim_sizes)
205 | {
206 | // TODO: Add exception checking that the number of elements in the data container is the same as the
207 | // product of the sizes of the dimensions that were given
208 |
209 | }
210 |
211 | template
212 | TensorInterface>::TensorInterface(dim_container&& dim_sizes, data_container&& data)
213 | : _data(data), _rank(dim_sizes.size()), _dim_sizes(dim_sizes)
214 | {
215 | // TODO: Add exception checking that the number of elements in the data container is the same as the
216 | // product of the sizes of the dimensions that were given
217 |
218 | }
219 |
220 | template template
221 | TensorInterface>::TensorInterface(const TensorExpression& expression)
222 | : _data(expression.size()), _dim_sizes(expression.dim_sizes()), _rank(expression.rank())
223 | {
224 | for (size_type i = 0; i != size(); ++i) _data[i] = expression[i];
225 | }
226 |
227 | template
228 | void TensorInterface>::initialize(const data_type min, const data_type max)
229 | {
230 | std::random_device rand_device;
231 | std::mt19937 gen(rand_device());
232 | std::uniform_real_distribution<> dist(min, max);
233 | for (auto& element : _data) element = static_cast(dist(gen));
234 | }
235 |
236 | template template
237 | DT& TensorInterface>::operator()(IF dim_one_index, IR... other_dim_indices)
238 | {
239 | return _data[DynamicMapper::indices_to_index(_dim_sizes, dim_one_index, other_dim_indices...)];
240 | }
241 |
242 | template template
243 | DT TensorInterface>::operator()(IF dim_one_index, IR... other_dim_indices) const
244 | {
245 | return _data[DynamicMapper::indices_to_index(_dim_sizes, dim_one_index, other_dim_indices...)];
246 | }
247 |
248 | } // End namespace ftl
249 | #endif // FTL_TENSOR_DYNAMIC_CPU_HPP
250 |
--------------------------------------------------------------------------------
/tensor/tensor_expression_dynamic_cpu.hpp:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------
2 | /// @file Header file for tensor expressions dynamic container and cpu specialization for tensor library.
3 | // ----------------------------------------------------------------------------------------------------------
4 |
5 | /*
6 | * ----------------------------------------------------------------------------------------------------------
7 | * Tensor is free software; you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published
9 | * by the Free Software Foundation; either version 2 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * Tensor is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License along
18 | * with tensor; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 | * ----------------------------------------------------------------------------------------------------------
21 | */
22 |
23 | #ifndef FTL_TENSOR_EXPRESSIONS_DYNAMIC_CPU_HPP
24 | #define FTL_TENSOR_EXPRESSIONS_DYNAMIC_CPU_HPP
25 |
26 | #include "tensor_expression_interface.hpp"
27 |
28 | namespace ftl {
29 |
30 | // Specialization for tensor expression with dynamic container and cpu implemenation traits
31 | template
32 | class TensorExpression> {
33 | public:
34 | // ---------------------------------------- ALIAS'S -----------------------------------------------------
35 | using traits = TensorTraits;
36 | using size_type = typename traits::size_type;
37 | using data_type = typename traits::data_type;
38 | using container_type = typename traits::container_type;
39 | using data_container = typename traits::data_container;
40 | using dim_container = typename traits::dim_container;
41 | // ------------------------------------------------------------------------------------------------------
42 |
43 | // ------------------------------------------------------------------------------------------------------
44 | /// @brief Gets a pointer to the expression.
45 | /// @return A non-const pointer to the expression.
46 | // ------------------------------------------------------------------------------------------------------
47 | Expression* expression() { return static_cast(this); }
48 |
49 | // ------------------------------------------------------------------------------------------------------
50 | /// @brief Gets a const pointer to the expression.
51 | /// @return A const pointer to the expression.
52 | // ------------------------------------------------------------------------------------------------------
53 | const Expression* expression() const { return static_cast(this); }
54 |
55 | // ------------------------------------------------------------------------------------------------------
56 | //! @brief Gets a reference to the Tensor expression.
57 | //! @return A reference to the Tensor expression E.
58 | // ------------------------------------------------------------------------------------------------------
59 | operator Expression&() { return static_cast(*this); }
60 |
61 | // ------------------------------------------------------------------------------------------------------
62 | //! @brief Gets a constant reference to the Tensor expression.
63 | //! @return A constant reference to the Tensror expression E.
64 | // ------------------------------------------------------------------------------------------------------
65 | operator Expression const&() const { return static_cast(*this); }
66 |
67 | // ------------------------------------------------------------------------------------------------------
68 | //! @brief Returns the size of the expression
69 | //! @return The size of the tensor_expression
70 | // ------------------------------------------------------------------------------------------------------
71 | size_type size() const { return expression()->size(); }
72 |
73 | // ------------------------------------------------------------------------------------------------------
74 | /// @brief Returns the rank of the expression
75 | /// @return The rank of the expression
76 | // ------------------------------------------------------------------------------------------------------
77 | size_type rank() const { return expression()->rank(); }
78 |
79 | // ------------------------------------------------------------------------------------------------------
80 | //! @brief Gets the sizes of the all the dimensions of the expression.
81 | //! @return A constant reference to the dimension size vector of the expression
82 | // ------------------------------------------------------------------------------------------------------
83 | const dim_container& dim_sizes() const { return expression()->dim_sizes(); }
84 |
85 | // ------------------------------------------------------------------------------------------------------
86 | //! @brief Gets and element from the Tensor expression data.
87 | //! @param[in] i The element in the expression which must be fetched.
88 | //! @return The value of the element at position i of the expression data.
89 | // ------------------------------------------------------------------------------------------------------
90 | inline data_type& operator[](size_type i) { return expression()->operator[](i); }
91 |
92 | // ------------------------------------------------------------------------------------------------------
93 | //! @brief Gets and element from the Tensor expression data.
94 | //! @param[in] i The element in the expression which must be fetched.
95 | //! @return The value of the element at position i of the expression data.
96 | // ------------------------------------------------------------------------------------------------------
97 | inline const data_type& operator[](size_type i) const { return expression()->operator[](i); }
98 | };
99 |
100 | } // End namespace ftl
101 | #endif // FTL_TENSOR_EXPRESSIONS_DYNAMIC_CPU_HPP
102 |
--------------------------------------------------------------------------------
/tensor/tensor_expression_interface.hpp:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------
2 | /// @file Header file for tensor expression interface for tensor library.
3 | // ----------------------------------------------------------------------------------------------------------
4 |
5 | /*
6 | * ----------------------------------------------------------------------------------------------------------
7 | * Tensor is free software; you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published
9 | * by the Free Software Foundation; either version 2 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * Tensor is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License along
18 | * with tensor; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 | * ----------------------------------------------------------------------------------------------------------
21 | */
22 |
23 | #ifndef FTL_TENSOR_EXPRESSION_INTERFACE_HPP
24 | #define FTL_TENSOR_EXPRESSION_INTERFACE_HPP
25 |
26 | #include "tensor_traits.hpp"
27 |
28 | namespace ftl {
29 |
30 | // NOTE : All specializations are defined in their own files as:
31 | // - tensor_expressions__,hpp
32 | //
33 | // : where
34 | // - container_type = type of container (static_or dynamic)
35 | // - device_type = type of device (cpu gpu, any)
36 | //
37 | // any = not yet implemented for a specific device, or can operate on both
38 |
39 |
40 | // ----------------------------------------------------------------------------------------------------------
41 | /// @class TensorExpression
42 | /// @brief Defines a general tensor expression so that opertions on tensor expressions can be defined
43 | /// the syntax of the operations to look as they would mathematically.
44 | /// @tparam Expression The expression
45 | /// @tparam Traits The traits which define the expression, for example specifying that the
46 | /// expression uses static containers and GPU implemenations
47 | // ----------------------------------------------------------------------------------------------------------
48 | template
49 | class TensorExpression;
50 |
51 | } // End namespace ftl
52 | #endif // FTL_TENSOR_EXPRESSION_INTERFACE_HPP
53 |
--------------------------------------------------------------------------------
/tensor/tensor_expression_static_cpu.hpp:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------
2 | /// @file Header file for tensor expressions static container and cpu specialization for tensor library.
3 | // ----------------------------------------------------------------------------------------------------------
4 |
5 | /*
6 | * ----------------------------------------------------------------------------------------------------------
7 | * Tensor is free software; you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published
9 | * by the Free Software Foundation; either version 2 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * Tensor is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License along
18 | * with tensor; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 | * ----------------------------------------------------------------------------------------------------------
21 | */
22 |
23 | #ifndef FTL_TENSOR_EXPRESSIONS_STATIC_CPU_HPP
24 | #define FTL_TENSOR_EXPRESSIONS_STATIC_CPU_HPP
25 |
26 | #include "tensor_expression_interface.hpp"
27 |
28 | // NOTE: Some of the template parameters are abbreviated as (IMHO) it looks cleaner, so:
29 | // - DT = Dtype = type of data used
30 | // - SF = SizeFirst = size of the first dimension
31 | // - SR = SizeRest = sizes of the rest of the dimensions
32 |
33 | namespace ftl {
34 |
35 | // Specialization for tensor expression with static container and cpu implementation traits
36 | template
37 | class TensorExpression> {
38 | public:
39 | // ---------------------------------------- ALIAS'S -----------------------------------------------------
40 | using traits = TensorTraits;
41 | using size_type = typename traits::size_type;
42 | using data_type = typename traits::data_type;
43 | using container_type = typename traits::container_type;
44 | using data_container = typename traits::data_container;
45 | using dim_container = typename traits::dim_container;
46 | // ------------------------------------------------------------------------------------------------------
47 |
48 | // ------------------------------------------------------------------------------------------------------
49 | /// @brief Gets a pointer to the expression.
50 | /// @return A non-const pointer to the expression.
51 | // ------------------------------------------------------------------------------------------------------
52 | Expression* expression() { return static_cast(this); }
53 |
54 | // ------------------------------------------------------------------------------------------------------
55 | /// @brief Gets a const pointer to the expression.
56 | /// @return A const pointer to the expression.
57 | // ------------------------------------------------------------------------------------------------------
58 | const Expression* expression() const { return static_cast(this); }
59 |
60 | // ------------------------------------------------------------------------------------------------------
61 | //! @brief Gets a reference to the Tensor expression.
62 | //! @return A reference to the Tensor expression E.
63 | // ------------------------------------------------------------------------------------------------------
64 | operator Expression&() { return static_cast(*this); }
65 |
66 | // ------------------------------------------------------------------------------------------------------
67 | //! @brief Gets a constant reference to the Tensor expression.
68 | //! @return A constant reference to the Tensror expression E.
69 | // ------------------------------------------------------------------------------------------------------
70 | operator Expression const&() const { return static_cast(*this); }
71 |
72 | // ------------------------------------------------------------------------------------------------------
73 | /// @brief Returns the size of the expression
74 | /// @return The size of the expression
75 | // ------------------------------------------------------------------------------------------------------
76 | constexpr size_type size() const { return expression()->size(); }
77 |
78 | // ------------------------------------------------------------------------------------------------------
79 | /// @brief Returns the rank of the expression
80 | /// @return The rank of the expression
81 | // ------------------------------------------------------------------------------------------------------
82 | constexpr size_type rank() const { return expression()->rank(); }
83 |
84 | // ------------------------------------------------------------------------------------------------------
85 | //! @brief Gets the sizes of the all the dimensions of the expression.
86 | //! @return A constant reference to the dimension size vector of the expression
87 | // ------------------------------------------------------------------------------------------------------
88 | constexpr const dim_container& dim_sizes() const { return expression()->dim_sizes(); }
89 |
90 | // ------------------------------------------------------------------------------------------------------
91 | //! @brief Gets and element from the Tensor expression data.
92 | //! @param[in] i The element in the expression which must be fetched.
93 | //! @return The value of the element at position i of the expression data.
94 | // ------------------------------------------------------------------------------------------------------
95 | inline data_type& operator[](size_type i) { return expression()->operator[](i); }
96 |
97 | // ------------------------------------------------------------------------------------------------------
98 | //! @brief Gets and element from the Tensor expression data.
99 | //! @param[in] i The element in the expression which must be fetched.
100 | //! @return The value of the element at position i of the expression data.
101 | // ------------------------------------------------------------------------------------------------------
102 | inline const data_type& operator[](size_type i) const { return expression()->operator[](i); }
103 | };
104 |
105 | } // End namespace ftl
106 | #endif // FTL_TENSOR_EXPRESSIONS_STATIC_CPU_HPP
107 |
--------------------------------------------------------------------------------
/tensor/tensor_expressions.hpp:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------
2 | /// @file Header file for tensor expressions for the tensor library -- includes all partial specializations
3 | /// for the tensor expressions. The file is intended to be included in an aplication where all tensor
4 | /// expression functionality is required. It will reduce compilation time, so when using a specific
5 | /// expression implementation -- say static contatiers with a GPU -- include only that file.
6 | // ----------------------------------------------------------------------------------------------------------
7 |
8 | /*
9 | * ----------------------------------------------------------------------------------------------------------
10 | * Tensor is free software; you can redistribute it and/or modify
11 | * it under the terms of the GNU General Public License as published
12 | * by the Free Software Foundation; either version 2 of the License, or
13 | * (at your option) any later version.
14 | *
15 | * Tensor is distributed in the hope that it will be useful,
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | * GNU General Public License for more details.
19 | *
20 | * You should have received a copy of the GNU General Public License along
21 | * with tensor; if not, write to the Free Software Foundation,
22 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 | * ----------------------------------------------------------------------------------------------------------
24 | */
25 |
26 | #ifndef FTL_TENSOR_EXPRESSIONS_HPP
27 | #define FTL_TENSOR_EXPRESSIONS_HPP
28 |
29 | #include "tensor_expression_dynamic_cpu.hpp"
30 | #include "tensor_expression_static_cpu.hpp"
31 |
32 | #endif // FTL_TENSOR_EXPRESSIONS_HPP
33 |
34 |
--------------------------------------------------------------------------------
/tensor/tensor_operations.hpp:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------
2 | /// @file Header file for tensor operations for tensor library.
3 | // ----------------------------------------------------------------------------------------------------------
4 |
5 | /*
6 | * ----------------------------------------------------------------------------------------------------------
7 | * Tensor is free software; you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published
9 | * by the Free Software Foundation; either version 2 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * Tensor is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License along
18 | * with tensor; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 | * ----------------------------------------------------------------------------------------------------------
21 | */
22 |
23 | #ifndef FTL_TENSOR_OPERATIONS_HPP
24 | #define FTL_TENSOR_OPERATIONS_HPP
25 |
26 | #include "tensor_addition.hpp"
27 | #include "tensor_subtraction.hpp"
28 |
29 | // Unnamed namespace so that operations are available everywhere
30 | namespace {
31 |
32 | // ----------------------------------------------------------------------------------------------------------
33 | /// @brief Adds two tensor expressions
34 | /// @param[in] x The first expression to add
35 | /// @param[in] y The second expression to add
36 | /// @return The result of the addition of the two tensor_expressions.
37 | /// @tparam E1 The type of the first expression for the addition
38 | /// @tparam E2 The type of the second expression for the addition
39 | /// @tparam T1 The traits of the first tensors -- for addition the traits for the returned tensor are
40 | /// the same as the first tensor for additio
41 | /// @tparam T2 The traits of the second expression
42 | // ----------------------------------------------------------------------------------------------------------
43 | template
44 | const ftl::TensorAddition operator+(ftl::TensorExpression const& x,
45 | ftl::TensorExpression const& y)
46 | {
47 | return ftl::TensorAddition(x, y);
48 | }
49 |
50 | // ----------------------------------------------------------------------------------------------------------
51 | /// @brief Subtracts two tensor expressions
52 | /// @param[in] x The first expression to subtract from
53 | /// @param[in] y The second expression to subtract with
54 | /// @return The result of the subtraction of the two tensor_expressions.
55 | /// @tparam E1 The type of the first expression for the subtraction
56 | /// @tparam E2 The type of the second expression for the subtraction
57 | /// @tparam T1 The traits of the first tensors -- for subtraction the traits for the returned tensor are
58 | /// the same as the first tensor for additio
59 | /// @tparam T2 The traits of the second expression
60 | // ----------------------------------------------------------------------------------------------------------
61 | template
62 | const ftl::TensorSubtraction operator-(ftl::TensorExpression const& x,
63 | ftl::TensorExpression const& y)
64 | {
65 | return ftl::TensorSubtraction(x, y);
66 | }
67 |
68 | } // End unnamed namespace
69 | #endif // FTL_TENSOR_OPERATIONS_HPP
70 |
--------------------------------------------------------------------------------
/tensor/tensor_static_cpu.hpp:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------
2 | /// @file Header file for tensor specialization with a static container using the cpu.
3 | // ----------------------------------------------------------------------------------------------------------
4 |
5 | /*
6 | * ----------------------------------------------------------------------------------------------------------
7 | * Tensor is free software; you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published
9 | * by the Free Software Foundation; either version 2 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * Tensor is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License along
18 | * with tensor; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 | * ----------------------------------------------------------------------------------------------------------
21 | */
22 |
23 | #ifndef FTL_TENSOR_STATIC_CPU_HPP
24 | #define FTL_TENSOR_STATIC_CPU_HPP
25 |
26 | #include
27 | #include "mapper.hpp"
28 | #include "tensor_expression_static_cpu.hpp" // NOTE: Only including expression specialization for
29 | // static cpu implementation -- all specializations
30 | // are provided by tensor_expressions.hpp
31 |
32 | #include
33 |
34 | // NOTE : Using long template names results in extremely bulky code, so the following abbreviations are
35 | // used to reduve the bulk for template parameters:
36 | // - DT = Dtype = data type
37 | // - SF = SizeFirst = size of first dimension
38 | // - SR = SizeRest = size of other dimensions
39 | namespace ftl {
40 |
41 | // Forward declaration of TensorInterface so that we can provide the specialization
42 | template
43 | class TensorInterface;
44 |
45 | // Type alias for static cpu tensor to make the code more readable
46 | template
47 | using StaticTensorCpu = TensorInterface>;
48 |
49 | // Specialization for a tensor using a static container and a CPU device
50 | template
51 | class TensorInterface> : public TensorExpression<
52 | StaticTensorCpu ,
53 | TensorTraits> {
54 | public:
55 | // ---------------------------------------- ALIAS'S -----------------------------------------------------
56 | using traits = TensorTraits;
57 | using size_type = typename traits::size_type;
58 | using data_type = typename traits::data_type;
59 | using container_type = typename traits::container_type;
60 | using data_container = typename container_type::data_container;
61 | using dim_container = typename container_type::dim_container;
62 | // ------------------------------------------------------------------------------------------------------
63 |
64 | // ------------------------------------------------------------------------------------------------------
65 | /// @brief Default constructor, converts the compile time list of dimension sizes to an array
66 | // ------------------------------------------------------------------------------------------------------
67 | TensorInterface();
68 |
69 | // ------------------------------------------------------------------------------------------------------
70 | /// @brief Constructor for when the data is given as an lvalue
71 | /// @param[in] data The data to use for the tensor
72 | // ------------------------------------------------------------------------------------------------------
73 | TensorInterface(data_container& data);
74 |
75 | // ------------------------------------------------------------------------------------------------------
76 | /// @brief Constructor for when the data is specified as a literal list
77 | /// @param[in] first_value The first value in the literal list -- must be data_type
78 | /// @param[in] other_values The other values which make up the data
79 | /// @tparam TR The type of the rest of the values
80 | // ------------------------------------------------------------------------------------------------------
81 | template
82 | TensorInterface(DT&& first_value, TR&&... other_values);
83 |
84 | // ------------------------------------------------------------------------------------------------------
85 | /// @brief Constructor for creation from a tensor expression -- this is only used for simple
86 | /// expressions (which do not modify the rank and/or dimension sizes) -- such as addition
87 | /// and subtraction. Rank modifying expressions-- such as multiplication and slicing -- have
88 | /// specialized constructors (to be implemented).
89 | /// @param[in] expression The expression instance to create the static tensor from
90 | /// @tparam Expression The type of the expression
91 | // ------------------------------------------------------------------------------------------------------
92 | template
93 | TensorInterface(const TensorExpression& expression);
94 |
95 | // ------------------------------------------------------------------------------------------------------
96 | /// @brief Gets the rank (number of dimensions) of the tensor
97 | /// @return The rank (number of dimensions) of the tensor
98 | // ------------------------------------------------------------------------------------------------------
99 | constexpr size_type rank() const { return sizeof...(SR) + 1; }
100 |
101 | // ------------------------------------------------------------------------------------------------------
102 | /// @brief Gets the size (total number of elements) in the tensor
103 | /// @return The size of the tensor
104 | // ------------------------------------------------------------------------------------------------------
105 | constexpr size_type size() const { return _data.size(); }
106 |
107 | // TODO: Add out of range exception
108 | // ------------------------------------------------------------------------------------------------------
109 | /// @brief Gets the size (total number of elements) in a specific dimension of the tensor, if the
110 | /// dimension is valid
111 | /// @param[in] dim The dimension to get the size of
112 | /// @return The size of the requested dimension of the tensor if valid, otherwise 0
113 | // ------------------------------------------------------------------------------------------------------
114 | inline size_type size(const size_type dim) const { return dim < rank() ? _dim_sizes[dim] : 0; }
115 |
116 | // ------------------------------------------------------------------------------------------------------
117 | /// @brief Gets a reference to the container holding the sizes of the dimensions for the tensor
118 | /// @return A constant reference to the dimension sizes of the tensor
119 | // ------------------------------------------------------------------------------------------------------
120 | constexpr const dim_container& dim_sizes() const { return _dim_sizes; }
121 |
122 | // ------------------------------------------------------------------------------------------------------
123 | /// @brief Initializes each element of the tensor between a range using a uniform ditribution
124 | /// @param[in] min The minimum value of an element after the initialization
125 | /// @param[in] max The max value of an element after the initialization
126 | // ------------------------------------------------------------------------------------------------------
127 | void initialize(const data_type min, const data_type max);
128 |
129 | // ------------------------------------------------------------------------------------------------------
130 | /// @brief Gets an element from the tensor
131 | /// @param[in] i The index of the element in the tensor
132 | /// @return A reference to the element at the index i in the tensor
133 | // ------------------------------------------------------------------------------------------------------
134 | inline data_type& operator[](size_type i) { return _data[i]; }
135 |
136 | // ------------------------------------------------------------------------------------------------------
137 | /// @brief Gets an element from the tensor
138 | /// @param[in] i The index of the element in the tensor
139 | /// @return The value of the element at the index i in the tensor
140 | // ------------------------------------------------------------------------------------------------------
141 | inline const data_type& operator[](size_type i) const { return _data[i]; }
142 |
143 | // ------------------------------------------------------------------------------------------------------
144 | /// @brief Gets the element at a given index for each dimension of a tensor -- there is no bound
145 | /// checking as bound checking implementations will be provided through .at()
146 | /// @param[in] index_dim_one The index of the element in dimension 1
147 | /// @param[in] index_dim_other The index of the element in the other dimensions
148 | /// @tparam IF The type of the first index parameter
149 | /// @tparam IR The types of the rest of the index parameters
150 | /// @return A reference to the element at the position given by the indices
151 | // ------------------------------------------------------------------------------------------------------
152 | template
153 | DT& operator()(IF index_dim_one, IR... index_dim_other);
154 |
155 | // ------------------------------------------------------------------------------------------------------
156 | /// @brief Gets the element at a given index for each dimension of a tensor -- there is no bound
157 | /// checking as bound checking implementations will be provided through .at()
158 | /// @param[in] index_dim_one The index of the element in dimension 1
159 | /// @param[in] index_dim_other The index of the element in the other dimensions
160 | /// @tparam IF The type of the first index parameter
161 | /// @tparam IR The types of the rest of the index parameters
162 | /// @return The value of the element at the position given by the indices
163 | // ------------------------------------------------------------------------------------------------------
164 | template
165 | DT operator()(IF index_dim_one, IR... index_dim_other) const;
166 | private:
167 | data_container _data; //!< The data container which holds all the data
168 | dim_container _dim_sizes; //!< The sizes of the dimensions for the tensor
169 | };
170 |
171 | // ----------------------------------------------- IMPLEMENTATIONS ------------------------------------------
172 |
173 | // ------------------------------------------------- PUBLIC -------------------------------------------------
174 |
175 | template
176 | TensorInterface>::TensorInterface()
177 | {
178 | // Convert the nano::list of dimension sizes to a constant array
179 | _dim_sizes = nano::runtime_converter::to_array();
180 | };
181 |
182 | template
183 | TensorInterface>::TensorInterface(data_container& data)
184 | : _data(data)
185 | {
186 | // Convert the nano::list of dimension sizes to a constant array
187 | _dim_sizes = nano::runtime_converter::to_array();
188 | }
189 |
190 | template template
191 | TensorInterface>::TensorInterface(DT&& first_value, TR&&... other_values)
192 | : _data{{std::forward(first_value), std::forward(other_values)...}}
193 | {
194 | // Convert the nano::list of dimension sizes to a constant array
195 | _dim_sizes = nano::runtime_converter::to_array();
196 | }
197 |
198 | template template
199 | TensorInterface>::TensorInterface(const TensorExpression& expression)
200 | {
201 | // Convert the nano::list of dimension sizes to a constant array
202 | _dim_sizes = nano::runtime_converter::to_array();
203 | for (size_type i = 0; i != size(); ++i) _data[i] = expression[i];
204 | }
205 |
206 | template
207 | void TensorInterface>::initialize(const data_type min, const data_type max)
208 | {
209 | std::random_device rand_device;
210 | std::mt19937 gen(rand_device());
211 | std::uniform_real_distribution<> dist(min, max);
212 | for (auto& element : _data) element = static_cast(dist(gen));
213 | }
214 |
215 | template template
216 | DT& TensorInterface>::operator()(IF dim_one_index, IR... other_dim_indices)
217 | {
218 | using dimension_sizes = typename container_type::dimension_sizes;
219 | return _data[StaticMapper::indices_to_index(dim_one_index, other_dim_indices...)];
220 | }
221 |
222 | template template
223 | DT TensorInterface>::operator()(IF dim_one_index, IR... other_dim_indices) const
224 | {
225 | using dimension_sizes = typename container_type::dimension_sizes;
226 | return _data[StaticMapper::indices_to_index(dim_one_index, other_dim_indices...)];
227 | }
228 |
229 | } // End namespace ftl
230 | #endif // FTL_TENSOR_STATIC_CPU_HPP
231 |
--------------------------------------------------------------------------------
/tensor/tensor_subtraction.hpp:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------
2 | /// @file Header file for tensor sybtraction for tensor library.
3 | // ----------------------------------------------------------------------------------------------------------
4 |
5 | /*
6 | * ----------------------------------------------------------------------------------------------------------
7 | * Tensor is free software; you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published
9 | * by the Free Software Foundation; either version 2 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * Tensor is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License along
18 | * with tensor; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 | * ----------------------------------------------------------------------------------------------------------
21 | */
22 |
23 | #ifndef FTL_TENSOR_SUBTRACTION_HPP
24 | #define FTL_TENSOR_SUBTRACTION_HPP
25 |
26 | #include "tensor_expressions.hpp"
27 |
28 | namespace ftl {
29 |
30 | // ----------------------------------------------------------------------------------------------------------
31 | /// @class TensorSubtraction
32 | /// @brief Expression class for calculating the subtraction of two tensors.
33 | /// @tparam E1 The first expression for subtraction
34 | /// @tparam E2 The second expression for subtraction
35 | /// @tparam T1 The traits of the first expression
36 | /// @tparam T2 The traits if the second expression
37 | // ----------------------------------------------------------------------------------------------------------
38 | template
39 | class TensorSubtraction : public TensorExpression, T1> {
40 | public:
41 | using traits = T1;
42 | using dim_container = typename traits::dim_container;
43 | using size_type = typename traits::size_type;
44 | using data_type = typename traits::data_type;
45 | private:
46 | E1 const& _x; //!< First expression for subtraction
47 | E2 const& _y; //!< Second expression for subtraction
48 | public:
49 | // ------------------------------------------------------------------------------------------------------
50 | /// @brief Sets the expressions for subtraction and checks that they have the same ranks and dimension
51 | /// @param[in] x The first expression for subtraction.
52 | /// @param[in] y The second expression for subtraction
53 | // ------------------------------------------------------------------------------------------------------
54 | TensorSubtraction(TensorExpression const& x, TensorExpression const& y);
55 |
56 | // ------------------------------------------------------------------------------------------------------
57 | /// @brief Gets the sizes of the all the dimensions of the expression.
58 | /// @return A constant reference to the dimension size vector of the expression
59 | // ------------------------------------------------------------------------------------------------------
60 | inline const dim_container& dim_sizes() const { return _x.dim_sizes(); }
61 |
62 | // ------------------------------------------------------------------------------------------------------
63 | /// @brief Returns the size of the expression.
64 | /// @return The size of the tensor_subtraction.
65 | // ------------------------------------------------------------------------------------------------------
66 | inline const size_type size() const { return _x.size(); }
67 |
68 | // ------------------------------------------------------------------------------------------------------
69 | /// @brief Returns the size of the expression.
70 | /// @return The size of the tensor_subtraction.
71 | // ------------------------------------------------------------------------------------------------------
72 | inline const size_type rank() const { return _x.rank(); }
73 |
74 | // ------------------------------------------------------------------------------------------------------
75 | /// @brief Adds two elements (one from each Tensor) from the tensor expression data.
76 | /// @param[in] i The element in the expression which must be fetched.
77 | /// @return The result of the subtraction of the Tensors.
78 | // ------------------------------------------------------------------------------------------------------
79 | inline data_type operator[](size_type i) const { return _x[i] - _y[i]; }
80 | };
81 |
82 | // ------------------------------------- SUBTRACTION IMPLEMENTATIONS -------------------------------------------
83 |
84 | template
85 | TensorSubtraction::TensorSubtraction(const TensorExpression& x,
86 | const TensorExpression& y)
87 | : _x(x), _y(y)
88 | {
89 | // TODO: Add error throwing
90 | // Check that the ranks are equal
91 | if (x.rank() != y.rank() && x.dim_sizes() != y.dim_sizes()) ;
92 | // Throw error here
93 | }
94 |
95 | } // End namespace ftl
96 | #endif // FTL_TENSOR_SUBTRACTION_HPP
97 |
--------------------------------------------------------------------------------
/tensor/tensor_traits.hpp:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------
2 | /// @file Header file for tensor traits for tensor library.
3 | // ----------------------------------------------------------------------------------------------------------
4 |
5 | /*
6 | * ----------------------------------------------------------------------------------------------------------
7 | * Tensor is free software; you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published
9 | * by the Free Software Foundation; either version 2 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * Tensor is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License along
18 | * with tensor; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 | * ----------------------------------------------------------------------------------------------------------
21 | */
22 |
23 | #ifndef FTL_TENSOR_TRAITS_HPP
24 | #define FTL_TENSOR_TRAITS_HPP
25 |
26 | #include "tensor_container.hpp"
27 |
28 | namespace ftl {
29 |
30 | // So that the code is more readable -- using an int rather than an enum since it will make
31 | // for easy integration with other libraries that want to enable compile time device selection
32 | using device = short;
33 |
34 | static constexpr device CPU = 0;
35 | static constexpr device GPU = 1;
36 |
37 | // ----------------------------------------------------------------------------------------------------------
38 | /// @struct TensorTraits
39 | /// @brief Traits class which specifies parameters for a tensor, such as what type of container it uses
40 | /// and what type of device the computations should be performed on
41 | /// @tparam Dtype The type of data used by the container
42 | /// @tparam DeviceType The type of device used for computation -- CPU or GPU
43 | /// @tparam DimSizes The sizes of each of the dimensions of the tensor -- an optional parameters.
44 | /// This parameter is used to determine the container type -- static if the dimension sizes are
45 | /// specified or dynamic if they are not.
46 | // ----------------------------------------------------------------------------------------------------------
47 | template
48 | struct TensorTraits;
49 |
50 | // Specialize for static container
51 | template
52 | struct TensorTraits {
53 | // ---------------------------------------- ALIAS'S -----------------------------------------------------
54 | using data_type = Dtype;
55 | using container_type = TensorContainer;
56 | using data_container = typename container_type::data_container;
57 | using dim_container = typename container_type::dim_container;
58 | using size_type = typename container_type::size_type;
59 | // ------------------------------------------------------------------------------------------------------
60 | static constexpr device device_type = DeviceType;
61 | };
62 |
63 | // Specialize for dynamic container
64 | template
65 | struct TensorTraits {
66 | // ---------------------------------------- ALIAS'S -----------------------------------------------------
67 | using data_type = Dtype;
68 | using container_type = TensorContainer;
69 | using data_container = typename container_type::data_container;
70 | using dim_container = typename container_type::dim_container;
71 | using size_type = typename container_type::size_type;
72 | // ------------------------------------------------------------------------------------------------------};
73 | static constexpr device device_type = DeviceType;
74 | };
75 |
76 | } // End namespace ftl
77 | #endif // FTL_TENSOR_TRAITS_HPP
78 |
--------------------------------------------------------------------------------
/tests/Makefile:
--------------------------------------------------------------------------------
1 | ########################################################################################
2 | # EXECUTABLE NAME #
3 | # #
4 | # NOTE: The following conventions are used: #
5 | # #
6 | # - CU = CUDA related variables #
7 | # - CX = C++ related variables #
8 | ########################################################################################
9 |
10 | EXE := test_suite
11 | CONTAINER_EXE := container_suite
12 | OPERATIONS_EXE := operations_suite
13 | TENSOR_EXE := tensor_suite
14 | TRAITS_EXE := traits_suite
15 |
16 |
17 | ########################################################################################
18 | # COMPILERS #
19 | # #
20 | # NOTE: Compiling with cuda because GPU support will be added #
21 | ########################################################################################
22 |
23 | HOST_COMPILER := clang++
24 | NVCC := nvcc -ccbin $(HOST_COMPILER)
25 | CXX := clang++
26 |
27 | ########################################################################################
28 | # INCLUDE DIRECTORIES #
29 | ########################################################################################
30 |
31 | CU_INC :=
32 | CX_INC :=
33 |
34 | ########################################################################################
35 | # LIBRARIES #
36 | ########################################################################################
37 |
38 | CU_LIBS :=
39 | CX_LIBS := -lboost_unit_test_framework
40 |
41 | CU_LDIR :=
42 | CX_LDIR :=
43 |
44 | ########################################################################################
45 | # COMPILER FLAGS #
46 | # #
47 | # NOTE: To enable compiler warnings, remove -w and replace with : #
48 | # --compiler-options -Wall #
49 | ########################################################################################
50 |
51 | CU_FLAGS :=
52 | CX_FLAGS := -std=c++11 -w
53 |
54 | DG_FLAGS := -g
55 | RE_FLAGS := -O3
56 |
57 | TP_FLAGS := $(CX_FLAGS)
58 |
59 | ########################################################################################
60 | # TARGET RULES #
61 | #######################################################################################
62 |
63 | .PHONY: all container operations tensor traits
64 |
65 | all: debug
66 |
67 | debug: CX_FLAGS += $(DG_FLAGS)
68 | debug: build_tests
69 |
70 | operations_tests.o: operations_tests.cpp
71 | $(CXX) $(CU_INC) $(CU_FLAGS) $(CX_INC) $(CX_FLAGS) -o $@ -c $<
72 |
73 | container_tests.o: container_tests.cpp
74 | $(CXX) $(CU_INC) $(CU_FLAGS) $(CX_INC) $(CX_FLAGS) -o $@ -c $<
75 |
76 | tensor_tests.o: tensor_tests.cpp
77 | $(CXX) $(CU_INC) $(CU_FLAGS) $(CX_INC) $(CX_FLAGS) -o $@ -c $<
78 |
79 | traits_tests.o: traits_tests.cpp
80 | $(CXX) $(CU_INC) $(CU_FLAGS) $(CX_INC) $(CX_FLAGS) -o $@ -c $<
81 |
82 | tests.o: tests.cpp
83 | $(CXX) $(CU_INC) $(CU_FLAGS) $(CX_INC) $(CX_FLAGS) -o $@ -c $<
84 |
85 | build_tests: container_tests.o tensor_tests.o traits_tests.o operations_tests.o tests.o
86 | $(CXX) -o $(EXE) $+ $(CU_LDIR) $(CU_LIBS) $(CX_LDIR) $(CX_LIBS)
87 |
88 | container: CX_FLAGS += -DSTAND_ALONE
89 | container: container_tests.o
90 | $(CXX) -o $(CONTAINER_EXE) $+ $(CU_LDIR) $(CU_LIBS) $(CX_LDIR) $(CX_LIBS)
91 |
92 | operations: CX_FLAGS += -DSTAND_ALONE
93 | operations: operations_tests.o
94 | $(CXX) -o $(OPERATIONS_EXE) $+ $(CU_LDIR) $(CU_LIBS) $(CX_LDIR) $(CX_LIBS)
95 |
96 | tensor: CX_FLAGS += -DSTAND_ALONE
97 | tensor: tensor_tests.o
98 | $(CXX) -o $(TENSOR_EXE) $+ $(CU_LDIR) $(CU_LIBS) $(CX_LDIR) $(CX_LIBS)
99 |
100 | traits: CX_FLAGS += -DSTAND_ALONE
101 | traits: traits_tests.o
102 | $(CXX) -o $(TRAITS_EXE) $+ $(CU_LDIR) $(CU_LIBS) $(CX_LDIR) $(CX_LIBS)
103 |
104 | clean:
105 | rm -rf *.o
106 | rm -rf $(EXE)
107 | rm -rf $(CONTAINER_EXE)
108 | rm -rf $(OPERATIONS_EXE)
109 | rm -rf $(TENSOR_EXE)
110 | rm -rf $(TRAITS_EXE)
111 |
--------------------------------------------------------------------------------
/tests/container_tests.cpp:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------
2 | /// @file container_tests.cpp
3 | /// @brief Test suites for container tests
4 | // ----------------------------------------------------------------------------------------------------------
5 |
6 | #define BOOST_TEST_DYN_LINK
7 | #ifdef STAND_ALONE
8 | #define BOOST_TEST_MODULE ContainerTests
9 | #endif
10 | #include
11 |
12 | #ifndef FTL_TENSOR_CONTAINER_HPP
13 | #include "../tensor/tensor_container.hpp"
14 | #endif
15 |
16 | BOOST_AUTO_TEST_SUITE( TensorContainerSuite)
17 |
18 | // TODO: Add tests that conver entire container functionality
19 |
20 | BOOST_AUTO_TEST_CASE( canCreateStaticContainer )
21 | {
22 | // Create a container specifying the dimension sizes
23 | ftl::TensorContainer A;
24 |
25 | BOOST_CHECK( A.size() == 6 );
26 | }
27 |
28 | BOOST_AUTO_TEST_CASE( canCreateDynamicContainer )
29 | {
30 | // Create a container without specifying the dimensions
31 | ftl::TensorContainer A;
32 |
33 | BOOST_CHECK( A.size() == 0 );
34 | }
35 |
36 | BOOST_AUTO_TEST_SUITE_END()
37 |
--------------------------------------------------------------------------------
/tests/operations_tests.cpp:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------
2 | /// @file operations_tests.cpp
3 | /// @brief Test suite for tensor operationstests
4 | // ----------------------------------------------------------------------------------------------------------
5 |
6 | #define BOOST_TEST_DYN_LINK
7 | #ifdef STAND_ALONE
8 | #define BOOST_TEST_MODULE OperationsTests
9 | #endif
10 | #include
11 |
12 | #include "../tensor/tensor.hpp"
13 | #include "../tensor/tensor_operations.hpp"
14 |
15 | #include
16 |
17 | BOOST_AUTO_TEST_SUITE( OperationsSuite )
18 |
19 | // -------------------------------------------- ADDITION ---------------------------------------------------
20 |
21 | BOOST_AUTO_TEST_CASE( canAdd2StaticTensors )
22 | {
23 | ftl::Tensor A{ 1, 2, 3, 4 };
24 | ftl::Tensor B{ 1, 2, 3, 4 };
25 |
26 | auto C = A + B;
27 | ftl::Tensor D = A + B;
28 |
29 | BOOST_CHECK( C[0] == 2 );
30 | BOOST_CHECK( D[0] == 2 );
31 | BOOST_CHECK( C[1] == 4 );
32 | BOOST_CHECK( D[1] == 4 );
33 | BOOST_CHECK( C[2] == 6 );
34 | BOOST_CHECK( D[2] == 6 );
35 | BOOST_CHECK( C[3] == 8 );
36 | BOOST_CHECK( D[3] == 8 );
37 | }
38 |
39 | BOOST_AUTO_TEST_CASE( canAdd2DynamicTensors )
40 | {
41 | // Create 2 dynamic tensors of rank 2
42 | // with dimension size of 2x2
43 | ftl::Tensor A{ 2, 2 };
44 | ftl::Tensor B{ 2, 2 };
45 |
46 | // Intialize A to have values of 1, and B to have values of 2
47 | A.initialize(1, 1);
48 | B.initialize(2, 2);
49 |
50 | auto C = A + B;
51 | ftl::Tensor D = A + B;
52 |
53 | BOOST_CHECK( C[0] == 3 );
54 | BOOST_CHECK( D[0] == 3 );
55 | BOOST_CHECK( C[1] == 3 );
56 | BOOST_CHECK( D[1] == 3 );
57 | BOOST_CHECK( C[2] == 3 );
58 | BOOST_CHECK( D[2] == 3 );
59 | BOOST_CHECK( C[3] == 3 );
60 | BOOST_CHECK( D[3] == 3 );
61 | }
62 |
63 | BOOST_AUTO_TEST_CASE( canAddAStaticAndDynamicTensorToGetAStaticTensor )
64 | {
65 | ftl::Tensor A{ 1, 2, 3, 4 };
66 | ftl::Tensor B{ 2, 2 };
67 |
68 | // Initialize B with values of 10
69 | B.initialize(10, 10);
70 |
71 | // Addition takes the traits of the first tensor in the addition (A)
72 | // So C and D are static tensors since A is a static tensor
73 | auto C = A + B;
74 | ftl::Tensor D = A + B;
75 |
76 | BOOST_CHECK( C[0] == 11 );
77 | BOOST_CHECK( D[0] == 11 );
78 | BOOST_CHECK( C[1] == 12 );
79 | BOOST_CHECK( D[1] == 12 );
80 | BOOST_CHECK( C[2] == 13 );
81 | BOOST_CHECK( D[2] == 13 );
82 | BOOST_CHECK( C[3] == 14 );
83 | BOOST_CHECK( D[3] == 14 );
84 |
85 | }
86 |
87 | BOOST_AUTO_TEST_CASE( canAddADynamicAndStaticTensorToGetADynamicTensor )
88 | {
89 | ftl::Tensor A{ 2, 2 };
90 | ftl::Tensor B{ 1, 2, 3, 4 };
91 |
92 | // Initialize A with values of 10
93 | A.initialize(10, 10);
94 |
95 | // Addition takes the traits of the first tensor in the addition (A)
96 | // So C and D are dynamic tensors since A is a dynamic tensor
97 | auto C = A + B;
98 | ftl::Tensor D = A + B;
99 |
100 | BOOST_CHECK( C[0] == 11 );
101 | BOOST_CHECK( D[0] == 11 );
102 | BOOST_CHECK( C[1] == 12 );
103 | BOOST_CHECK( D[1] == 12 );
104 | BOOST_CHECK( C[2] == 13 );
105 | BOOST_CHECK( D[2] == 13 );
106 | BOOST_CHECK( C[3] == 14 );
107 | BOOST_CHECK( D[3] == 14 );
108 | }
109 |
110 | // ---------------------------------------------- SUBTRACTION -----------------------------------------------
111 |
112 | BOOST_AUTO_TEST_CASE( canSubtract2StaticTensors )
113 | {
114 | // Tensor dimensions are stored down (col) then across (row)
115 | ftl::Tensor A{ 1, 2, 3, 4 };
116 | ftl::Tensor B{ 2, 4, 6, 8 };
117 |
118 | auto C = A - B;
119 | ftl::Tensor D = A - B;
120 |
121 | // Using auto makes a TensorSubtraction<...> which doesn't have
122 | // and overloaded () operator at present as the expression classes
123 | // are supposed to be used to create new tensors (as is done for D)
124 | BOOST_CHECK( C[0] == -1 );
125 | BOOST_CHECK( D(0, 0) == -1 );
126 | BOOST_CHECK( C[1] == -2 );
127 | BOOST_CHECK( D(1, 0) == -2 );
128 | BOOST_CHECK( C[2] == -3 );
129 | BOOST_CHECK( D(0, 1) == -3 );
130 | BOOST_CHECK( C[3] == -4 );
131 | BOOST_CHECK( D(1, 1) == -4 );
132 | }
133 |
134 | BOOST_AUTO_TEST_SUITE_END()
135 |
--------------------------------------------------------------------------------
/tests/tensor_tests.cpp:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------
2 | /// @file tensor_tests.cpp
3 | /// @brief Test suite for tensor tests
4 | // ----------------------------------------------------------------------------------------------------------
5 |
6 | #define BOOST_TEST_DYN_LINK
7 | #ifdef STAND_ALONE
8 | #define BOOST_TEST_MODULE TensorTests
9 | #endif
10 | #include
11 |
12 | #include "../tensor/tensor.hpp"
13 | #include "../tensor/tensor_operations.hpp"
14 |
15 | BOOST_AUTO_TEST_SUITE( TensorSuite)
16 |
17 | BOOST_AUTO_TEST_CASE( canCreateDynamicTensor )
18 | {
19 | // Define the type of the dynamic tensor using the general tensor type
20 | using dynamic_tensor_gen = ftl::Tensor;
21 |
22 | // Define the type of the dynamic tensor using the specialized CPU definition
23 | using dynamic_tensor_cpu = ftl::DynamicTensorCpu;
24 |
25 | // Create a container using the traits class -- need to specify the rank of dynamic tensors
26 | dynamic_tensor_gen A(3); // Rank 3 tensor
27 | dynamic_tensor_cpu B(4); // Rank 4 tensor
28 |
29 | BOOST_CHECK( A.rank() == 3 );
30 | BOOST_CHECK( B.rank() == 4 );
31 | }
32 |
33 | BOOST_AUTO_TEST_CASE( canCreateDynamicTensorFromDimensionSizesAdnData )
34 | {
35 | std::vector dimension_sizes = { 2 , 3 };
36 | std::vector data = { 1.f, 2.f , // e00, xe, y0
37 | 3.f, 4.f , // x0, x1, y1
38 | 5.f, 6.f }; // x0, x1, y2
39 |
40 | // Use the data to create the tensor -- will have rank 2
41 | ftl::Tensor A(dimension_sizes, data);
42 | auto tensor_data = A.data();
43 |
44 | BOOST_CHECK( A.size() == 6 );
45 | BOOST_CHECK( A.rank() == 2 );
46 | BOOST_CHECK( tensor_data[0] == 1.f );
47 | BOOST_CHECK( tensor_data[1] == 2.f );
48 | BOOST_CHECK( tensor_data[2] == 3.f );
49 | BOOST_CHECK( tensor_data[3] == 4.f );
50 | BOOST_CHECK( tensor_data[4] == 5.f );
51 | BOOST_CHECK( tensor_data[5] == 6.f );
52 | }
53 |
54 | BOOST_AUTO_TEST_CASE( canSetAndGetElementOfDynamicTensor )
55 | {
56 | // Create a dynamic tensor specifying the sizes of the dimensions
57 | ftl::DynamicTensorCpu A( {3, 3, 3} );
58 |
59 | // Set 2nd element
60 | A(1, 0, 0) = 4;
61 |
62 | BOOST_CHECK( A.size() == 27 );
63 | BOOST_CHECK( A.rank() == 3 );
64 | BOOST_CHECK( A(1, 0, 0) == 4 );
65 | }
66 |
67 | BOOST_AUTO_TEST_CASE( canGetSizeOfASpecificDimensionOfADynamicTensor )
68 | {
69 | ftl::Tensor A( {1, 2, 3} );
70 |
71 | BOOST_CHECK( A.size(0) == 1 );
72 | BOOST_CHECK( A.size(1) == 2 );
73 | BOOST_CHECK( A.size(2) == 3 );
74 | }
75 |
76 | // -------------------------------------------- STATIC CPU --------------------------------------------------
77 |
78 | BOOST_AUTO_TEST_CASE( canCreateDefaultStaticTensor )
79 | {
80 | // Define the type of the static tensor using the general tensor type
81 | // This defines a rank 3 tensor with all dimensions sizes with a value of 2
82 | using static_tensor_gen = ftl::Tensor;
83 |
84 | // Define the type of the static tensor using the specialized CPU definition
85 | // This defines a rank 3 tensor with all dimensions sizes with a value of 2
86 | using static_tensor_cpu = ftl::StaticTensorCpu;
87 |
88 | static_tensor_gen A;
89 | static_tensor_cpu B;
90 |
91 | auto dim_sizes_a = A.dim_sizes();
92 | auto dim_sizes_b = B.dim_sizes();
93 |
94 | BOOST_CHECK( A.size() == 8 );
95 | BOOST_CHECK( B.size() == 8 );
96 | BOOST_CHECK( A.rank() == 3 );
97 | BOOST_CHECK( B.rank() == 3 );
98 | BOOST_CHECK( B.size() == 8 );
99 | BOOST_CHECK( dim_sizes_a[0] == 2 );
100 | BOOST_CHECK( dim_sizes_a[1] == 2 );
101 | BOOST_CHECK( dim_sizes_a[2] == 2 );
102 | BOOST_CHECK( dim_sizes_b[0] == 2 );
103 | BOOST_CHECK( dim_sizes_b[1] == 2 );
104 | BOOST_CHECK( dim_sizes_b[2] == 2 );
105 | }
106 |
107 | BOOST_AUTO_TEST_CASE( canCreateStaticTensorWithDataFromContainer )
108 | {
109 | // Create data for the static tensor
110 | std::array data{ {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f} };
111 |
112 | // Create a container specifying the dimension sizes
113 | ftl::Tensor A(data);
114 |
115 | BOOST_CHECK( A.size() == 6 );
116 | BOOST_CHECK( A[0] == 1.0f );
117 | BOOST_CHECK( A[1] == 2.0f );
118 | BOOST_CHECK( A[2] == 3.0f );
119 | BOOST_CHECK( A[3] == 4.0f );
120 | BOOST_CHECK( A[4] == 5.0f );
121 | BOOST_CHECK( A[5] == 6.0f );
122 | }
123 |
124 | BOOST_AUTO_TEST_CASE( canCreateStaticTensorWithLiteralList )
125 | {
126 | // Create a container specifying the dimension sizes
127 | ftl::Tensor A{ 1.0, 2.0, 3.0, 4.0 };
128 |
129 | BOOST_CHECK( A.size() == 4 );
130 | BOOST_CHECK( A[0] == 1.0 );
131 | BOOST_CHECK( A[1] == 2.0 );
132 | BOOST_CHECK( A[2] == 3.0 );
133 | BOOST_CHECK( A[3] == 4.0 );
134 | }
135 |
136 | BOOST_AUTO_TEST_CASE( canDetermineDimensionSizesCorrectly )
137 | {
138 | std::array data{ 1.0, 2.0 };
139 |
140 | // Create a container specifying the dimension sizes
141 | ftl::StaticTensorCpu A{ 1, 2, 3, 4 };
142 | ftl::StaticTensorCpu B;
143 | ftl::StaticTensorCpu C(data);
144 |
145 | auto a_dim_sizes = A.dim_sizes();
146 | auto b_dim_sizes = B.dim_sizes();
147 | auto c_dim_sizes = C.dim_sizes();
148 |
149 | BOOST_CHECK( a_dim_sizes[0] == 2 );
150 | BOOST_CHECK( a_dim_sizes[1] == 2 );
151 | BOOST_CHECK( b_dim_sizes[0] == 3 );
152 | BOOST_CHECK( b_dim_sizes[1] == 3 );
153 | BOOST_CHECK( c_dim_sizes[0] == 2 );
154 | }
155 |
156 | BOOST_AUTO_TEST_CASE( canGetAndSetElementOfStaticTensor )
157 | {
158 | ftl::Tensor A{4, 3, 2, 1};
159 |
160 | // Set 2nd element of the tensor
161 | A(1, 0) = 12;
162 |
163 | // Get 2nd element of the tensor
164 | int element = A(1, 0);
165 |
166 | BOOST_CHECK( element == 12 );
167 | }
168 |
169 | BOOST_AUTO_TEST_CASE( mappingOfMultipleDimensionsIsCorrect )
170 | {
171 | // Create a tensor and fill it with some data. Data values are the indecies of the element
172 | // to show the mapping, however, 1 indexing is used since an integer value can't have leading 0's
173 | // so:
174 | // value 111 = indices 0, 0, 0 for dim 0, 1, 2 respecively
175 | // value 212 = indices 1, 0, 1 for dim 0, 1, 2 respectively
176 | ftl::StaticTensorCpu A{ 111, 211, 121, 221 ,
177 | 112, 212, 122, 222 };
178 |
179 | BOOST_CHECK( A(0, 1, 1) == 122 );
180 | BOOST_CHECK( A(1, 0, 1) == 212 );
181 | BOOST_CHECK( A(1, 1, 0) == 221 );
182 | BOOST_CHECK( A(1, 0, 0) == 211 );
183 | }
184 |
185 | BOOST_AUTO_TEST_CASE( canInitializeAStaticTensor )
186 | {
187 | // Create a 2x2x2 tensor with initial value
188 | ftl::Tensor A{ 110, 120, 210, 220, 111, 121, 211, 221 };
189 |
190 | // Modify all values by initializing them all to 1
191 | A.initialize(1, 1);
192 |
193 | BOOST_CHECK( A(0, 0, 0) == 1 );
194 | }
195 |
196 | BOOST_AUTO_TEST_CASE( canGetSizeOfASpecificDimensionOfAStaticTensor )
197 | {
198 | ftl::Tensor A;
199 |
200 | BOOST_CHECK( A.size(0) == 1 );
201 | BOOST_CHECK( A.size(1) == 2 );
202 | BOOST_CHECK( A.size(2) == 3 );
203 | }
204 | BOOST_AUTO_TEST_SUITE_END()
205 |
--------------------------------------------------------------------------------
/tests/tests.cpp:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------
2 | /// @file tests.cpp
3 | /// @brief Test suite for all tests
4 | // ----------------------------------------------------------------------------------------------------------
5 |
6 | #define BOOST_TEST_DYN_LINK
7 | #define BOOST_TEST_MODULE TensorTests
8 | #include
9 |
--------------------------------------------------------------------------------
/tests/traits_tests.cpp:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------------------------------------
2 | /// @file traits_tests.cpp
3 | /// @brief Test suite for traits tests
4 | // ----------------------------------------------------------------------------------------------------------
5 |
6 | #define BOOST_TEST_DYN_LINK
7 | #ifdef STAND_ALONE
8 | #define BOOST_TEST_MODULE TraitsTests
9 | #endif
10 | #include
11 |
12 | #include "../tensor/tensor_traits.hpp"
13 |
14 | BOOST_AUTO_TEST_SUITE( TensorTraitsSuite)
15 |
16 | BOOST_AUTO_TEST_CASE( canDetermineStaticContainerFromTraits )
17 | {
18 | // Define traits for tensor
19 | // : int data type
20 | // : cpu implementation
21 | // : dimension sizes of 2 and 3
22 | using traits = ftl::TensorTraits;
23 |
24 | // Create a container using the traits class
25 | traits::container_type A;
26 |
27 | BOOST_CHECK( A.size() == 6 );
28 | }
29 |
30 | BOOST_AUTO_TEST_SUITE_END()
31 |
--------------------------------------------------------------------------------