00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00019 #ifndef _ARAGELI_functional_hpp_
00020 #define _ARAGELI_functional_hpp_
00021
00022 #include "config.hpp"
00023
00024 #include <functional>
00025
00026 #include "basefuncs.hpp"
00027 #include "function_traits.hpp"
00028 #include "factory.hpp"
00029 #include "cmp.hpp"
00030
00031
00032
00033
00034
00035
00036
00037
00038 namespace Arageli
00039 {
00040
00041
00042
00043
00044
00045
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00061
00062
00065
00066
00067
00069
00070
00071 template <typename T>
00072 bool is_prime (const T& x);
00073
00074
00075
00076
00077
00079 namespace func
00080 {
00081
00082 #define _ARAGELI_FUNC_BUILDER_1(NAME, RES) \
00083 template <typename T> \
00084 struct NAME : public std::unary_function<T, RES> \
00085 { \
00086 RES operator() (const T& x) const \
00087 { return Arageli::NAME(x); } \
00088 \
00089 RES operator() (T& x) const \
00090 { return Arageli::NAME(x); } \
00091 }
00092
00093 _ARAGELI_FUNC_BUILDER_1(is_null, bool);
00094 _ARAGELI_FUNC_BUILDER_1(is_unit, bool);
00095 _ARAGELI_FUNC_BUILDER_1(is_opposite_unit, bool);
00096 _ARAGELI_FUNC_BUILDER_1(is_negative, bool);
00097 _ARAGELI_FUNC_BUILDER_1(is_positive, bool);
00098 _ARAGELI_FUNC_BUILDER_1(sign, int);
00099 _ARAGELI_FUNC_BUILDER_1(is_prime, bool);
00100 _ARAGELI_FUNC_BUILDER_1(is_even, bool);
00101 _ARAGELI_FUNC_BUILDER_1(is_odd, bool);
00102
00103
00104 #undef _ARAGELI_FUNC_BUILDER_1
00105
00106 #define _ARAGELI_UNARY_OPERATOR_FUNC_BUILDER_1(NAME, OPER) \
00107 template <typename Arg, typename Res = Arg> \
00108 struct NAME : public std::unary_function<Arg, Res> \
00109 { \
00110 Res operator() (const Arg& x) const \
00111 { return OPER x; } \
00112 \
00113 Res operator() (Arg& x) const \
00114 { return OPER x; } \
00115 };
00116
00117 _ARAGELI_UNARY_OPERATOR_FUNC_BUILDER_1(indirection, *);
00118 _ARAGELI_UNARY_OPERATOR_FUNC_BUILDER_1(address, &);
00119 _ARAGELI_UNARY_OPERATOR_FUNC_BUILDER_1(unary_plus, +);
00120 _ARAGELI_UNARY_OPERATOR_FUNC_BUILDER_1(unary_minus, -);
00121 _ARAGELI_UNARY_OPERATOR_FUNC_BUILDER_1(logical_not, !);
00122 _ARAGELI_UNARY_OPERATOR_FUNC_BUILDER_1(bitwise_not, ~);
00123 _ARAGELI_UNARY_OPERATOR_FUNC_BUILDER_1(prefix_increment, ++);
00124 _ARAGELI_UNARY_OPERATOR_FUNC_BUILDER_1(prefix_decrement, --);
00125
00126
00127 template <typename Arg, typename Res = Arg>
00128 struct postfix_increment : public std::unary_function<Arg, Res>
00129 {
00130 Res operator() (const Arg& x) const
00131 { return x++; }
00132
00133 Res operator() (Arg& x) const
00134 { return x++; }
00135 };
00136
00137 template <typename Arg, typename Res = Arg>
00138 struct postfix_decrement : public std::unary_function<Arg, Res>
00139 {
00140 Res operator() (const Arg& x) const
00141 { return x--; }
00142
00143 Res operator() (Arg& x) const
00144 { return x--; }
00145 };
00146
00147
00148 #define _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_1(NAME, OPER) \
00149 template <typename Arg1, typename Arg2 = Arg1, \
00150 typename Res = Arg1> \
00151 struct NAME : public std::binary_function<Arg1, Arg2, Res> \
00152 { \
00153 Res operator() (const Arg1& x, const Arg2& y) const \
00154 { return OPER(x, y); } \
00155 \
00156 Res operator() (const Arg1& x, Arg2& y) const \
00157 { return OPER(x, y); } \
00158 \
00159 Res operator() (Arg1& x, const Arg2& y) const \
00160 { return OPER(x, y); } \
00161 \
00162 Res operator() (Arg1& x, Arg2& y) const \
00163 { return OPER(x, y); } \
00164 };
00165
00166 #define _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(NAME, OPER) \
00167 template <typename Arg1, typename Arg2 = Arg1, \
00168 typename Res = Arg1> \
00169 struct NAME : public std::binary_function<Arg1, Arg2, Res> \
00170 { \
00171 Res operator() (const Arg1& x, const Arg2& y) const \
00172 { return x OPER y; } \
00173 \
00174 Res operator() (const Arg1& x, Arg2& y) const \
00175 { return x OPER y; } \
00176 \
00177 Res operator() (Arg1& x, const Arg2& y) const \
00178 { return x OPER y; } \
00179 \
00180 Res operator() (Arg1& x, Arg2& y) const \
00181 { return x OPER y; } \
00182 };
00183
00184 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(plus, +);
00185 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(minus, -);
00186 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(multiplies, *);
00187 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(divides, /);
00188 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(modulus, %);
00189 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(logical_or, ||);
00190 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(logical_and, &&);
00191 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(equal_to, ==);
00192 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(not_equal_to, !=);
00193 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(greater, >);
00194 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(less, <);
00195 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(greater_equal, >=);
00196 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(less_equal, <=);
00197 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(bitwise_or, |);
00198 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(bitwise_and, &);
00199 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(bitwise_xor, ^);
00200 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(shift_left, <<);
00201 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(shift_right, >>);
00202
00203
00204 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(assign, =);
00205 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(assign_plus, +=);
00206 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(assign_minus, -=);
00207 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(assign_multiplies, *=);
00208 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(assign_divides, /=);
00209 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(assign_modulus, %=);
00210 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(assign_bitwise_or, |=);
00211 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(assign_bitwise_and, &=);
00212 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(assign_bitwise_xor, ^=);
00213 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(assign_shift_left, <<=);
00214 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(assign_shift_right, >>=);
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(right_assign_plus, +=);
00254 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(right_assign_minus, -=);
00255 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(right_assign_multiplies, *=);
00256 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(right_assign_divides, /=);
00257 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(right_assign_modulus, %=);
00258 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(right_assign_bitwise_or, |=);
00259 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(right_assign_bitwise_and, &=);
00260 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(right_assign_bitwise_xor, ^=);
00261 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(right_assign_shift_left, <<=);
00262 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_2(right_assign_shift_right, >>=);
00263
00264 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_1
00265 (left_assign_plus, Arageli::left_assign_plus);
00266 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_1
00267 (left_assign_minus, Arageli::left_assign_minus);
00268 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_1
00269 (left_assign_multiplies, Arageli::left_assign_multiplies);
00270 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_1
00271 (left_assign_divides, Arageli::left_assign_divides);
00272 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_1
00273 (left_assign_modulus, Arageli::left_assign_modulus);
00274 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_1
00275 (left_assign_bitwise_or, Arageli::left_assign_bitwise_or);
00276 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_1
00277 (left_assign_bitwise_and, Arageli::left_assign_bitwise_and);
00278 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_1
00279 (left_assign_bitwise_xor, Arageli::left_assign_bitwise_xor);
00280 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_1
00281 (left_assign_shift_left, Arageli::left_assign_shift_left);
00282 _ARAGELI_BINARY_OPERATOR_FUNC_BUILDER_1
00283 (left_assign_shift_right, Arageli::left_assign_shift_right);
00284
00285
00286 template <typename Arg, typename Res = Arg>
00287 struct parentheses_0 : public std::unary_function<Arg, Res>
00288 {
00289 Res operator() (const Arg& x) const { return x(); }
00290 Res operator() (Arg& x) const { return x(); }
00291 };
00292
00293 template <typename Arg1, typename Arg2, typename Res = Arg2>
00294 struct parentheses_1 : public std::binary_function<Arg1, Arg2, Res>
00295 {
00296 Res operator() (const Arg1& x, const Arg2& y) const { return x(y); }
00297 Res operator() (const Arg1& x, Arg2& y) const { return x(y); }
00298 Res operator() (Arg1& x, const Arg2& y) const { return x(y); }
00299 Res operator() (Arg1& x, Arg2& y) const { return x(y); }
00300 };
00301
00302 template <typename Arg1, typename Arg2, typename Res = Arg2>
00303 struct subscript : public std::binary_function<Arg1, Arg2, Res>
00304 {
00305 Res operator() (const Arg1& x, const Arg2& y) const { return x[y]; }
00306 Res operator() (const Arg1& x, Arg2& y) const { return x[y]; }
00307 Res operator() (Arg1& x, const Arg2& y) const { return x[y]; }
00308 Res operator() (Arg1& x, Arg2& y) const { return x[y]; }
00309 };
00310
00311 template
00312 <
00313 typename Func,
00314 typename Arg1 = typename Func::first_argument_type,
00315 typename Arg2 = typename Func::second_argument_type,
00316 typename Res = typename Func::result_type
00317 >
00318 struct swap_args : public std::binary_function<Arg1, Arg2, Res>
00319 {
00320 Res operator() (const Arg1& x, const Arg2& y) const
00321 { return base(y, x); }
00322
00323 Res operator() (const Arg1& x, Arg2& y) const
00324 { return base(y, x); }
00325
00326 Res operator() (Arg1& x, const Arg2& y) const
00327 { return base(y, x); }
00328
00329 Res operator() (Arg1& x, Arg2& y) const
00330 { return base(y, x); }
00331
00332 swap_args (const Func& func_a) : base(func_a) {}
00333
00334 Func base;
00335 };
00336
00337 template <typename Func>
00338 inline swap_args<Func> make_swap_args (const Func& func)
00339 { return swap_args<Func>(func); }
00340
00341
00342
00343 }
00344
00345 namespace gfunc
00346 {
00347
00348 #define _ARAGELI_FUNC_BUILDER_1(NAME, RES) \
00349 struct NAME \
00350 { \
00351 template <typename T> \
00352 RES operator() (const T& x) const \
00353 { return Arageli::NAME(x); } \
00354 };
00355
00356 #define _ARAGELI_FUNC_BUILDER_2(NAME, RES) \
00357 struct NAME \
00358 { \
00359 template <typename T1, typename T2> \
00360 RES operator() (const T1& x, const T2& y) const \
00361 { return Arageli::NAME(x, y); } \
00362 };
00363
00364 _ARAGELI_FUNC_BUILDER_2(cmp, int)
00365
00366
00367 template <typename Tag> struct by_tag;
00368
00369 #define ARAGELI_FUNCTIONAL_PREFIX_NONMODIF_UNARY_GFUNC_BY_TAG(NAME, OPER) \
00370 template<> struct by_tag<function_tag::NAME> \
00371 { \
00372 template <typename T1> \
00373 typename unary_function_traits \
00374 <function_tag::NAME, T1>::result_type \
00375 operator() (const T1& x) const \
00376 { return OPER x; } \
00377 };
00378
00379 ARAGELI_FUNCTIONAL_PREFIX_NONMODIF_UNARY_GFUNC_BY_TAG(indirection, *)
00380 ARAGELI_FUNCTIONAL_PREFIX_NONMODIF_UNARY_GFUNC_BY_TAG(address, &)
00381 ARAGELI_FUNCTIONAL_PREFIX_NONMODIF_UNARY_GFUNC_BY_TAG(unary_plus, +)
00382 ARAGELI_FUNCTIONAL_PREFIX_NONMODIF_UNARY_GFUNC_BY_TAG(unary_minus, -)
00383 ARAGELI_FUNCTIONAL_PREFIX_NONMODIF_UNARY_GFUNC_BY_TAG(logical_not, !)
00384 ARAGELI_FUNCTIONAL_PREFIX_NONMODIF_UNARY_GFUNC_BY_TAG(bitwise_not, ~)
00385
00386
00387 #define ARAGELI_FUNCTIONAL_PREFIX_MODIF_UNARY_GFUNC_BY_TAG(NAME, OPER) \
00388 template<> struct by_tag<function_tag::NAME> \
00389 { \
00390 template <typename T1> \
00391 typename unary_function_traits \
00392 <function_tag::NAME, T1>::result_type \
00393 operator() (T1& x) const \
00394 { return OPER x; } \
00395 };
00396
00397
00398 ARAGELI_FUNCTIONAL_PREFIX_MODIF_UNARY_GFUNC_BY_TAG(prefix_increment, ++)
00399 ARAGELI_FUNCTIONAL_PREFIX_MODIF_UNARY_GFUNC_BY_TAG(prefix_decrement, --)
00400
00401
00402 #define ARAGELI_FUNCTIONAL_POSTFIX_MODIF_UNARY_GFUNC_BY_TAG(NAME, OPER) \
00403 template<> struct by_tag<function_tag::NAME> \
00404 { \
00405 template <typename T1> \
00406 typename unary_function_traits \
00407 <function_tag::NAME, T1>::result_type \
00408 operator() (T1& x) const \
00409 { return x OPER; } \
00410 };
00411
00412
00413 ARAGELI_FUNCTIONAL_POSTFIX_MODIF_UNARY_GFUNC_BY_TAG(postfix_increment, ++)
00414 ARAGELI_FUNCTIONAL_POSTFIX_MODIF_UNARY_GFUNC_BY_TAG(postfix_decrement, --)
00415
00416
00417 #define ARAGELI_FUNCTIONAL_BINARY_GFUNC_BY_TAG(NAME, OPER) \
00418 template<> struct by_tag<function_tag::NAME> \
00419 { \
00420 template <typename T1, typename T2> \
00421 typename binary_function_traits \
00422 <function_tag::NAME, const T1&, const T2&>::result_type \
00423 operator() (const T1& x, const T2& y) const \
00424 { return x OPER y; } \
00425 };
00426
00427 ARAGELI_FUNCTIONAL_BINARY_GFUNC_BY_TAG(plus, +);
00428 ARAGELI_FUNCTIONAL_BINARY_GFUNC_BY_TAG(minus, -);
00429 ARAGELI_FUNCTIONAL_BINARY_GFUNC_BY_TAG(multiplies, *);
00430 ARAGELI_FUNCTIONAL_BINARY_GFUNC_BY_TAG(divides, /);
00431 ARAGELI_FUNCTIONAL_BINARY_GFUNC_BY_TAG(modulus, %);
00432 ARAGELI_FUNCTIONAL_BINARY_GFUNC_BY_TAG(logical_or, ||);
00433 ARAGELI_FUNCTIONAL_BINARY_GFUNC_BY_TAG(logical_and, &&);
00434 ARAGELI_FUNCTIONAL_BINARY_GFUNC_BY_TAG(equal_to, ==);
00435 ARAGELI_FUNCTIONAL_BINARY_GFUNC_BY_TAG(not_equal_to, !=);
00436 ARAGELI_FUNCTIONAL_BINARY_GFUNC_BY_TAG(greater, >);
00437 ARAGELI_FUNCTIONAL_BINARY_GFUNC_BY_TAG(less, <);
00438 ARAGELI_FUNCTIONAL_BINARY_GFUNC_BY_TAG(greater_equal, >=);
00439 ARAGELI_FUNCTIONAL_BINARY_GFUNC_BY_TAG(less_equal, <=);
00440 ARAGELI_FUNCTIONAL_BINARY_GFUNC_BY_TAG(bitwise_or, |);
00441 ARAGELI_FUNCTIONAL_BINARY_GFUNC_BY_TAG(bitwise_and, &);
00442 ARAGELI_FUNCTIONAL_BINARY_GFUNC_BY_TAG(bitwise_xor, ^);
00443 ARAGELI_FUNCTIONAL_BINARY_GFUNC_BY_TAG(shift_left, <<);
00444 ARAGELI_FUNCTIONAL_BINARY_GFUNC_BY_TAG(shift_right, >>);
00445
00446
00447 }
00448
00449 }
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459 #endif // #ifndef _ARAGELI_functional_hpp_
00460