1 /**
2 * @param mlpack_main.hpp
3 * @author Ryan Curtin
4 *
5 * This file, based on the value of the macro BINDING_TYPE, will define the
6 * macros necessary to compile an mlpack binding for the target language.
7 *
8 * This file should *only* be included by a program that is meant to be a
9 * command-line program or a binding to another language. This file also
10 * includes param_checks.hpp, which contains functions that are used to check
11 * parameter values at runtime.
12 *
13 * mlpack is free software; you may redistribute it and/or modify it under the
14 * terms of the 3-clause BSD license. You should have received a copy of the
15 * 3-clause BSD license along with mlpack. If not, see
16 * http://www.opensource.org/licenses/BSD-3-Clause for more information.
17 */
18 #ifndef MLPACK_CORE_UTIL_MLPACK_MAIN_HPP
19 #define MLPACK_CORE_UTIL_MLPACK_MAIN_HPP
20
21 #define BINDING_TYPE_CLI 0
22 #define BINDING_TYPE_TEST 1
23 #define BINDING_TYPE_PYX 2
24 #define BINDING_TYPE_JL 3
25 #define BINDING_TYPE_GO 4
26 #define BINDING_TYPE_R 5
27 #define BINDING_TYPE_MARKDOWN 128
28 #define BINDING_TYPE_UNKNOWN -1
29
30 #ifndef BINDING_TYPE
31 #define BINDING_TYPE BINDING_TYPE_UNKNOWN
32 #endif
33
34 #if (BINDING_TYPE == BINDING_TYPE_CLI) // This is a command-line executable.
35
36 // Matrices are transposed on load/save.
37 #define BINDING_MATRIX_TRANSPOSED true
38
39 #include <mlpack/bindings/cli/cli_option.hpp>
40 #include <mlpack/bindings/cli/print_doc_functions.hpp>
41
42 /**
43 * PRINT_PARAM_STRING() returns a string that contains the correct
44 * language-specific representation of a parameter's name.
45 */
46 #define PRINT_PARAM_STRING mlpack::bindings::cli::ParamString
47
48 /**
49 * PRINT_PARAM_VALUE() returns a string that contains a correct
50 * language-specific representation of a parameter's value.
51 */
52 #define PRINT_PARAM_VALUE mlpack::bindings::cli::PrintValue
53
54 /**
55 * PRINT_CALL() returns a string that contains the full language-specific
56 * representation of a call to an mlpack binding. The first argument should be
57 * the name of the binding, and all other arguments should be names of
58 * parameters followed by values (in the case where the preceding parameter is
59 * not a flag).
60 */
61 #define PRINT_CALL mlpack::bindings::cli::ProgramCall
62
63 /**
64 * PRINT_DATASET() returns a string that contains a correct language-specific
65 * representation of a dataset name.
66 */
67 #define PRINT_DATASET mlpack::bindings::cli::PrintDataset
68
69 /**
70 * PRINT_MODEL() returns a string that contains a correct language-specific
71 * representation of an mlpack model name.
72 */
73 #define PRINT_MODEL mlpack::bindings::cli::PrintModel
74
75 /**
76 * BINDING_IGNORE_CHECK() is an internally-used macro to determine whether or
77 * not a specific parameter check should be ignored.
78 */
79 #define BINDING_IGNORE_CHECK mlpack::bindings::cli::IgnoreCheck
80
81 namespace mlpack {
82 namespace util {
83
84 template<typename T>
85 using Option = mlpack::bindings::cli::CLIOption<T>;
86
87 }
88 }
89
90 static const std::string testName = "";
91 #include <mlpack/core/util/param.hpp>
92 #include <mlpack/bindings/cli/parse_command_line.hpp>
93 #include <mlpack/bindings/cli/end_program.hpp>
94
95 static void mlpackMain(); // This is typically defined after this include.
96
main(int argc,char ** argv)97 int main(int argc, char** argv)
98 {
99 // Parse the command-line options; put them into CLI.
100 mlpack::bindings::cli::ParseCommandLine(argc, argv);
101 // Enable timing.
102 mlpack::Timer::EnableTiming();
103
104 // A "total_time" timer is run by default for each mlpack program.
105 mlpack::Timer::Start("total_time");
106
107 mlpackMain();
108
109 // Print output options, print verbose information, save model parameters,
110 // clean up, and so forth.
111 mlpack::bindings::cli::EndProgram();
112 }
113
114 #elif(BINDING_TYPE == BINDING_TYPE_TEST) // This is a unit test.
115
116 // Matrices are not transposed on load/save.
117 #define BINDING_MATRIX_TRANSPOSED false
118
119 #include <mlpack/bindings/tests/test_option.hpp>
120 #include <mlpack/bindings/tests/ignore_check.hpp>
121 #include <mlpack/bindings/tests/clean_memory.hpp>
122
123 // These functions will do nothing.
124 #define PRINT_PARAM_STRING(A) std::string(" ")
125 #define PRINT_PARAM_VALUE(A, B) std::string(" ")
126 #define PRINT_DATASET(A) std::string(" ")
127 #define PRINT_MODEL(A) std::string(" ")
128
129 /**
130 * PRINT_CALL() returns a string that contains the full language-specific
131 * representation of a call to an mlpack binding. The first argument should be
132 * the name of the binding, and all other arguments should be names of
133 * parameters followed by values (in the case where the preceding parameter is
134 * not a flag).
135 */
136 #define PRINT_CALL(...) std::string(" ")
137
138 /**
139 * BINDING_IGNORE_CHECK() is an internally-used macro to determine whether or
140 * not a specific parameter check should be ignored.
141 */
142 #define BINDING_IGNORE_CHECK mlpack::bindings::tests::IgnoreCheck
143
144 namespace mlpack {
145 namespace util {
146
147 template<typename T>
148 using Option = mlpack::bindings::tests::TestOption<T>;
149
150 }
151 }
152
153 // testName symbol should be defined in each binding test file
154 #include <mlpack/core/util/param.hpp>
155
156 #elif(BINDING_TYPE == BINDING_TYPE_PYX) // This is a Python binding.
157
158 // Matrices are transposed on load/save.
159 #define BINDING_MATRIX_TRANSPOSED true
160
161 #include <mlpack/bindings/python/py_option.hpp>
162 #include <mlpack/bindings/python/print_doc_functions.hpp>
163
164 /**
165 * PRINT_PARAM_STRING() returns a string that contains the correct
166 * language-specific representation of a parameter's name.
167 */
168 #define PRINT_PARAM_STRING mlpack::bindings::python::ParamString
169
170 /**
171 * PRINT_PARAM_VALUE() returns a string that contains a correct
172 * language-specific representation of a parameter's value.
173 */
174 #define PRINT_PARAM_VALUE mlpack::bindings::python::PrintValue
175
176 /**
177 * PRINT_DATASET() returns a string that contains a correct language-specific
178 * representation of a dataset name.
179 */
180 #define PRINT_DATASET mlpack::bindings::python::PrintDataset
181
182 /**
183 * PRINT_MODEL() returns a string that contains a correct language-specific
184 * representation of an mlpack model name.
185 */
186 #define PRINT_MODEL mlpack::bindings::python::PrintModel
187
188 /**
189 * PRINT_CALL() returns a string that contains the full language-specific
190 * representation of a call to an mlpack binding. The first argument should be
191 * the name of the binding, and all other arguments should be names of
192 * parameters followed by values (in the case where the preceding parameter is
193 * not a flag).
194 */
195 #define PRINT_CALL mlpack::bindings::python::ProgramCall
196
197 /**
198 * BINDING_IGNORE_CHECK() is an internally-used macro to determine whether or
199 * not a specific parameter check should be ignored.
200 */
201 #define BINDING_IGNORE_CHECK mlpack::bindings::python::IgnoreCheck
202
203 namespace mlpack {
204 namespace util {
205
206 template<typename T>
207 using Option = mlpack::bindings::python::PyOption<T>;
208
209 }
210 }
211
212 static const std::string testName = "";
213 #include <mlpack/core/util/param.hpp>
214
215 #undef BINDING_NAME
216 #define BINDING_NAME(NAME) static \
217 mlpack::util::ProgramName \
218 io_programname_dummy_object = mlpack::util::ProgramName(NAME); \
219 namespace mlpack { \
220 namespace bindings { \
221 namespace python { \
222 std::string programName = NAME; \
223 } \
224 } \
225 }
226
227 PARAM_FLAG("verbose", "Display informational messages and the full list of "
228 "parameters and timers at the end of execution.", "v");
229 PARAM_FLAG("copy_all_inputs", "If specified, all input parameters will be deep"
230 " copied before the method is run. This is useful for debugging problems "
231 "where the input parameters are being modified by the algorithm, but can "
232 "slow down the code.", "");
233
234 // Nothing else needs to be defined---the binding will use mlpackMain() as-is.
235
236 #elif(BINDING_TYPE == BINDING_TYPE_JL) // This is a Julia binding.
237
238 // Matrices are transposed on load/save.
239 #define BINDING_MATRIX_TRANSPOSED true
240
241 #include <mlpack/bindings/julia/julia_option.hpp>
242 #include <mlpack/bindings/julia/print_doc_functions.hpp>
243
244 #define PRINT_PARAM_STRING mlpack::bindings::julia::ParamString
245 #define PRINT_PARAM_VALUE mlpack::bindings::julia::PrintValue
246 #define PRINT_DATASET mlpack::bindings::julia::PrintDataset
247 #define PRINT_MODEL mlpack::bindings::julia::PrintModel
248 #define PRINT_CALL mlpack::bindings::julia::ProgramCall
249 #define BINDING_IGNORE_CHECK mlpack::bindings::julia::IgnoreCheck
250
251 namespace mlpack {
252 namespace util {
253
254 template<typename T>
255 using Option = mlpack::bindings::julia::JuliaOption<T>;
256
257 }
258 }
259
260 static const std::string testName = "";
261 #include <mlpack/core/util/param.hpp>
262
263 #undef BINDING_NAME
264 #define BINDING_NAME(NAME) static \
265 mlpack::util::ProgramName \
266 io_programname_dummy_object = mlpack::util::ProgramName(NAME); \
267 namespace mlpack { \
268 namespace bindings { \
269 namespace julia { \
270 std::string programName = NAME; \
271 } \
272 } \
273 }
274
275 PARAM_FLAG("verbose", "Display informational messages and the full list of "
276 "parameters and timers at the end of execution.", "v");
277
278 // Nothing else needs to be defined---the binding will use mlpackMain() as-is.
279
280 #elif(BINDING_TYPE == BINDING_TYPE_GO) // This is a Go binding.
281
282 // Matrices are transposed on load/save.
283 #define BINDING_MATRIX_TRANSPOSED true
284
285 #include <mlpack/bindings/go/go_option.hpp>
286 #include <mlpack/bindings/go/print_doc_functions.hpp>
287
288 #define PRINT_PARAM_STRING mlpack::bindings::go::ParamString
289 #define PRINT_PARAM_VALUE mlpack::bindings::go::PrintValue
290 #define PRINT_DATASET mlpack::bindings::go::PrintDataset
291 #define PRINT_MODEL mlpack::bindings::go::PrintModel
292 #define PRINT_CALL mlpack::bindings::go::ProgramCall
293 #define BINDING_IGNORE_CHECK mlpack::bindings::go::IgnoreCheck
294
295 namespace mlpack {
296 namespace util {
297
298 template<typename T>
299 using Option = mlpack::bindings::go::GoOption<T>;
300
301 }
302 }
303
304 static const std::string testName = "";
305 #include <mlpack/core/util/param.hpp>
306
307 #undef BINDING_NAME
308 #define BINDING_NAME(NAME) static \
309 mlpack::util::ProgramName \
310 io_programname_dummy_object = mlpack::util::ProgramName(NAME); \
311 namespace mlpack { \
312 namespace bindings { \
313 namespace go { \
314 std::string programName = NAME; \
315 } \
316 } \
317 }
318
319 PARAM_FLAG("verbose", "Display informational messages and the full list of "
320 "parameters and timers at the end of execution.", "v");
321
322 // Nothing else needs to be defined---the binding will use mlpackMain() as-is.
323
324 #elif(BINDING_TYPE == BINDING_TYPE_R) // This is a R binding.
325
326 // This doesn't actually matter for this binding type.
327 #define BINDING_MATRIX_TRANSPOSED true
328
329 #include <mlpack/bindings/R/R_option.hpp>
330 #include <mlpack/bindings/R/print_doc_functions.hpp>
331
332 #define PRINT_PARAM_STRING mlpack::bindings::r::ParamString
333 #define PRINT_PARAM_VALUE mlpack::bindings::r::PrintValue
334 #define PRINT_DATASET mlpack::bindings::r::PrintDataset
335 #define PRINT_MODEL mlpack::bindings::r::PrintModel
336 #define PRINT_CALL(...) mlpack::bindings::r::ProgramCall(false, __VA_ARGS__)
337 #define BINDING_IGNORE_CHECK mlpack::bindings::r::IgnoreCheck
338
339 namespace mlpack {
340 namespace util {
341
342 template<typename T>
343 using Option = mlpack::bindings::r::ROption<T>;
344
345 }
346 }
347
348 static const std::string testName = "";
349 #include <mlpack/core/util/param.hpp>
350
351 PARAM_FLAG("verbose", "Display informational messages and the full list of "
352 "parameters and timers at the end of execution.", "v");
353
354 // Nothing else needs to be defined---the binding will use mlpackMain() as-is.
355
356 #elif BINDING_TYPE == BINDING_TYPE_MARKDOWN
357
358 // We use MARKDOWN_BINDING_NAME in BINDING_NAME(), BINDING_SHORT_DESC(),
359 // BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO()
360 // so it needs to be defined.
361 #ifndef MARKDOWN_BINDING_NAME
362 #error "MARKDOWN_BINDING_NAME must be defined when BINDING_TYPE is Markdown!"
363 #endif
364
365 // This value doesn't actually matter, but it needs to be defined as something.
366 #define BINDING_MATRIX_TRANSPOSED true
367
368 #include <mlpack/bindings/markdown/md_option.hpp>
369 #include <mlpack/bindings/markdown/print_doc_functions.hpp>
370
371 /**
372 * PRINT_PARAM_STRING() returns a string that contains the correct
373 * language-specific representation of a parameter's name.
374 */
375 #define PRINT_PARAM_STRING mlpack::bindings::markdown::ParamString
376
377 /**
378 * PRINT_PARAM_VALUE() returns a string that contains a correct
379 * language-specific representation of a parameter's value.
380 */
381 #define PRINT_PARAM_VALUE mlpack::bindings::markdown::PrintValue
382
383 /**
384 * PRINT_DATASET() returns a string that contains a correct language-specific
385 * representation of a dataset name.
386 */
387 #define PRINT_DATASET mlpack::bindings::markdown::PrintDataset
388
389 /**
390 * PRINT_MODEL() returns a string that contains a correct language-specific
391 * representation of an mlpack model name.
392 */
393 #define PRINT_MODEL mlpack::bindings::markdown::PrintModel
394
395 /**
396 * PRINT_CALL() returns a string that contains the full language-specific
397 * representation of a call to an mlpack binding. The first argument should be
398 * the name of the binding, and all other arguments should be names of
399 * parameters followed by values (in the case where the preceding parameter is
400 * not a flag).
401 */
402 #define PRINT_CALL mlpack::bindings::markdown::ProgramCall
403
404 /**
405 * BINDING_IGNORE_CHECK() is an internally-used macro to determine whether or
406 * not a specific parameter check should be ignored.
407 */
408 #define BINDING_IGNORE_CHECK mlpack::bindings::markdown::IgnoreCheck
409
410 // This doesn't actually matter for this binding type.
411 #define BINDING_MATRIX_TRANSPOSED true
412
413 namespace mlpack {
414 namespace util {
415
416 template<typename T>
417 using Option = mlpack::bindings::markdown::MDOption<T>;
418
419 }
420 }
421
422 #include <mlpack/core/util/param.hpp>
423 #include <mlpack/bindings/markdown/program_doc_wrapper.hpp>
424
425 #undef BINDING_NAME
426 #undef BINDING_SHORT_DESC
427 #undef BINDING_LONG_DESC
428 #undef BINDING_EXAMPLE
429 #undef BINDING_SEE_ALSO
430
431 #define BINDING_NAME(NAME) static \
432 mlpack::bindings::markdown::ProgramNameWrapper \
433 io_programname_dummy_object = \
434 mlpack::bindings::markdown::ProgramNameWrapper( \
435 MARKDOWN_BINDING_NAME, NAME);
436
437 #define BINDING_SHORT_DESC(SHORT_DESC) static \
438 mlpack::bindings::markdown::ShortDescriptionWrapper \
439 io_programshort_desc_dummy_object = \
440 mlpack::bindings::markdown::ShortDescriptionWrapper( \
441 MARKDOWN_BINDING_NAME, SHORT_DESC);
442
443 #define BINDING_LONG_DESC(LONG_DESC) static \
444 mlpack::bindings::markdown::LongDescriptionWrapper \
445 io_programlong_desc_dummy_object = \
446 mlpack::bindings::markdown::LongDescriptionWrapper( \
447 MARKDOWN_BINDING_NAME, []() { return std::string(LONG_DESC); });
448
449 #ifdef __COUNTER__
450 #define BINDING_EXAMPLE(EXAMPLE) static \
451 mlpack::bindings::markdown::ExampleWrapper \
452 JOIN(io_programexample_dummy_object_, __COUNTER__) = \
453 mlpack::bindings::markdown::ExampleWrapper(MARKDOWN_BINDING_NAME, \
454 []() { return(std::string(EXAMPLE)); });
455
456 #define BINDING_SEE_ALSO(DESCRIPTION, LINK) static \
457 mlpack::bindings::markdown::SeeAlsoWrapper \
458 JOIN(io_programsee_also_dummy_object_, __COUNTER__) = \
459 mlpack::bindings::markdown::SeeAlsoWrapper(MARKDOWN_BINDING_NAME, \
460 DESCRIPTION, LINK);
461 #else
462 #define BINDING_EXAMPLE(EXAMPLE) static \
463 mlpack::bindings::markdown::ExampleWrapper \
464 JOIN(JOIN(io_programexample_dummy_object_, __LINE__), opt) = \
465 mlpack::bindings::markdown::ExampleWrapper(MARKDOWN_BINDING_NAME, \
466 []() { return(std::string(EXAMPLE)); });
467
468 #define BINDING_SEE_ALSO(DESCRIPTION, LINK) static \
469 mlpack::bindings::markdown::SeeAlsoWrapper \
470 JOIN(JOIN(io_programsee_also_dummy_object_, __LINE__), opt) = \
471 mlpack::bindings::markdown::SeeAlsoWrapper(MARKDOWN_BINDING_NAME, \
472 DESCRIPTION, LINK);
473 #endif
474
475 PARAM_FLAG("verbose", "Display informational messages and the full list of "
476 "parameters and timers at the end of execution.", "v");
477
478 // CLI-specific parameters.
479 PARAM_FLAG("help", "Default help info.", "h");
480 PARAM_STRING_IN("info", "Print help on a specific option.", "", "");
481 PARAM_FLAG("version", "Display the version of mlpack.", "V");
482
483 // Python-specific parameters.
484 PARAM_FLAG("copy_all_inputs", "If specified, all input parameters will be deep"
485 " copied before the method is run. This is useful for debugging problems "
486 "where the input parameters are being modified by the algorithm, but can "
487 "slow down the code.", "");
488
489 #else
490
491 #error "Unknown binding type! Be sure BINDING_TYPE is defined if you are " \
492 "including <mlpack/core/util/mlpack_main.hpp>.";
493
494 #endif
495
496 #include "param_checks.hpp"
497
498 #endif
499