Last active
August 29, 2015 14:00
-
-
Save usagi/11204302 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <random> | |
| #include <iostream> | |
| #include <iomanip> | |
| #include <vector> | |
| #include <list> | |
| #include <forward_list> | |
| #include <map> | |
| #include <unordered_map> | |
| #include <algorithm> | |
| #include <chrono> | |
| #include <functional> | |
| #include <boost/any.hpp> | |
| #include <boost/property_tree/ptree.hpp> | |
| #include <glm/glm.hpp> | |
| namespace | |
| { | |
| auto print_time | |
| ( const std::function | |
| < auto(unsigned long, unsigned long)->void >& f | |
| , unsigned long number_of_steps | |
| , unsigned long number_of_objects | |
| ) | |
| -> void | |
| { | |
| using namespace std::chrono; | |
| const auto start = high_resolution_clock::now(); | |
| f( number_of_steps, number_of_objects ); | |
| const auto delta_time = high_resolution_clock::now() - start; | |
| std::cout << std::fixed << std::setprecision(2); | |
| if ( duration_cast< minutes >( delta_time ) > std::chrono::minutes(1) ) | |
| std::cout << " time: " << duration_cast< duration<double, minutes::period> >( delta_time ).count() << " [min.]\n"; | |
| else if ( duration_cast< std::chrono::seconds >( delta_time ) > seconds(1) ) | |
| std::cout << " time: " << duration_cast< duration<double, seconds::period> >( delta_time ).count() << " [sec.]\n"; | |
| else if ( duration_cast< std::chrono::milliseconds >( delta_time ) > milliseconds(1) ) | |
| std::cout << " time: " << duration_cast< duration<double, milliseconds::period> >( delta_time ).count() << " [ms]\n"; | |
| else if ( duration_cast< std::chrono::microseconds >( delta_time ) > microseconds(1) ) | |
| std::cout << " time: " << duration_cast< duration<double, microseconds::period> >( delta_time ).count() << " [us]\n"; | |
| else | |
| std::cout << " time: " << duration_cast< duration<double, nanoseconds::period> >( delta_time ).count() << " [ns]\n"; | |
| } | |
| class object_t | |
| { | |
| public: | |
| virtual auto mass(const double value) -> void = 0; | |
| virtual auto position(const glm::vec3& value) -> void = 0; | |
| virtual auto position() const -> glm::vec3 = 0; | |
| virtual auto action(const double delta_time, const glm::vec3& force) -> void = 0; | |
| }; | |
| class member_variable_object_t | |
| : public object_t | |
| { | |
| double _mass; | |
| glm::vec3 _position; | |
| glm::vec3 _velocity; | |
| public: | |
| auto mass(const double value) | |
| -> void override | |
| { _mass = value; } | |
| auto position(const glm::vec3& value) | |
| -> void override | |
| { _position = value; } | |
| auto position() const | |
| -> glm::vec3 override | |
| { return _position; } | |
| auto action(const double delta_time, const glm::vec3& force) | |
| -> void override | |
| { | |
| const auto vec3_delta_time = glm::vec3( delta_time ); | |
| const auto acceleration = force / glm::vec3( _mass ); | |
| _velocity += acceleration * vec3_delta_time; | |
| _position += _velocity * vec3_delta_time; | |
| } | |
| }; | |
| template < class T_map = std::map<std::string, boost::any> > | |
| class map_string_any_object_t | |
| : public object_t | |
| { | |
| T_map _properties; | |
| public: | |
| explicit map_string_any_object_t() | |
| : _properties | |
| ( { { "mass", 0 } | |
| , { "position", glm::vec3() } | |
| , { "velocity", glm::vec3() } | |
| } | |
| ) | |
| { } | |
| auto mass(const double value) | |
| -> void override | |
| { _properties["mass"] = value; } | |
| auto position(const glm::vec3& value) | |
| -> void override | |
| { _properties["position"] = value; } | |
| auto position() const | |
| -> glm::vec3 override | |
| { return boost::any_cast<const glm::vec3>( _properties.at("position") ); } | |
| auto action(const double delta_time, const glm::vec3& force) | |
| -> void override | |
| { | |
| const auto vec3_delta_time = glm::vec3( delta_time ); | |
| const auto acceleration = force / glm::vec3( boost::any_cast<double>( _properties["mass"] ) ); | |
| const auto velocity = boost::any_cast<glm::vec3&>( _properties["velocity"] ) += acceleration * vec3_delta_time; | |
| boost::any_cast<glm::vec3&>( _properties["position"] ) += velocity * vec3_delta_time; | |
| } | |
| }; | |
| class ptree_object_t | |
| : public object_t | |
| { | |
| boost::property_tree::ptree _properties; | |
| public: | |
| explicit ptree_object_t() | |
| { | |
| _properties.put( "mass", 0 ); | |
| property_from_glm_vec3( "position", glm::vec3() ); | |
| property_from_glm_vec3( "velocity", glm::vec3() ); | |
| } | |
| auto mass(const double value) | |
| -> void override | |
| { _properties.put("mass", value); } | |
| auto position(const glm::vec3& value) | |
| -> void override | |
| { | |
| _properties.put("position.x", value.x); | |
| _properties.put("position.y", value.y); | |
| _properties.put("position.z", value.z); | |
| } | |
| auto position() const | |
| -> glm::vec3 override | |
| { return glm_vec3_from_property("position"); } | |
| auto action(const double delta_time, const glm::vec3& force) | |
| -> void override | |
| { | |
| const auto vec3_delta_time = glm::vec3( delta_time ); | |
| const auto acceleration = force / glm::vec3( _properties.get<double>("mass") ); | |
| auto velocity = glm_vec3_from_property("velocity"); | |
| velocity += acceleration * vec3_delta_time; | |
| property_from_glm_vec3("velocity", velocity); | |
| auto position = glm_vec3_from_property("position"); | |
| position += velocity * vec3_delta_time; | |
| property_from_glm_vec3("position", position); | |
| } | |
| auto glm_vec3_from_property(const std::string& key) const | |
| -> glm::vec3 | |
| { | |
| return glm::vec3 | |
| ( _properties.get<double>( key + ".x" ) | |
| , _properties.get<double>( key + ".y" ) | |
| , _properties.get<double>( key + ".z" ) | |
| ); | |
| } | |
| auto property_from_glm_vec3(const std::string& key, const glm::vec3& v) | |
| -> void | |
| { | |
| _properties.put( key + ".x", v.x ); | |
| _properties.put( key + ".y", v.y ); | |
| _properties.put( key + ".z", v.z ); | |
| } | |
| }; | |
| template | |
| < template<class T, class Allocator=std::allocator<T> > class T_container | |
| , class T_object | |
| > | |
| auto test | |
| ( unsigned long number_of_steps | |
| , unsigned long number_of_objects | |
| ) | |
| -> void | |
| { | |
| T_container<T_object> objects( number_of_objects ); | |
| std::mt19937 rng( 0 ); | |
| std::normal_distribution<double> unorm_distribution( 0.0, 1.0 ); | |
| std::normal_distribution<double> snorm_distribution( -1.0, 1.0 ); | |
| for ( auto& object : objects ) | |
| { | |
| object.mass( unorm_distribution( rng ) ); | |
| object.position | |
| ( { snorm_distribution( rng ) | |
| , snorm_distribution( rng ) | |
| , snorm_distribution( rng ) | |
| } | |
| ); | |
| } | |
| const auto print_normalized_sum_of_positions = [ &objects ] | |
| { | |
| glm::vec3 sum; | |
| for ( const auto object : objects ) | |
| sum += object.position(); | |
| const auto normalized = glm::normalize( sum ); | |
| std::cout | |
| << std::fixed | |
| << std::setprecision(3) | |
| << normalized.x << " " | |
| << normalized.y << " " | |
| << normalized.z | |
| << "\n" | |
| ; | |
| }; | |
| std::cout << " normalized sum of positions(initial): "; | |
| print_normalized_sum_of_positions(); | |
| for ( auto n = 0; n < number_of_steps; ++n ) | |
| { | |
| const auto delta_time = unorm_distribution( rng ); | |
| for ( auto& object : objects ) | |
| object.action | |
| ( delta_time | |
| , { snorm_distribution( rng ) | |
| , snorm_distribution( rng ) | |
| , snorm_distribution( rng ) | |
| } | |
| ); | |
| } | |
| std::cout << " normalized sum of positions(final) : "; | |
| print_normalized_sum_of_positions(); | |
| } | |
| } | |
| auto main(int number_of_arguments, char** arguments) | |
| -> int | |
| { | |
| unsigned long number_of_steps = 1000; | |
| unsigned long number_of_objects = 1000; | |
| std::cout | |
| << "\n" | |
| " *** property_benchmark *** \n" | |
| " usage: ./a.out [number_of_steps] [number_of_objects]\n" | |
| " defaults are: " << number_of_steps << ", " << number_of_objects << "\n" | |
| " this program benchmarks:\n" | |
| " basic Newton's Equation of motion with Eular's method using:\n" | |
| " 1. objects container types { std::vector, std::list, std::forward_list } \n" | |
| " 2. object owned property types { basic member variable, boost::property_tree::ptree }\n" | |
| ; | |
| try | |
| { | |
| if ( number_of_arguments > 1 ) | |
| number_of_steps = std::stoul( arguments[1] ); | |
| if ( number_of_arguments > 2 ) | |
| number_of_objects = std::stoul( arguments[2] ); | |
| } | |
| catch( const std::invalid_argument& ) | |
| { | |
| std::cerr << " !!! warning: invalid argument. !!!\n"; | |
| } | |
| std::cout | |
| << "\n" | |
| "number_of_steps : " << number_of_steps << "\n" | |
| "number_of_objects: " << number_of_objects << "\n" | |
| ; | |
| // test run | |
| std::cout << "\n *** test running std::vector<basic_object_t>(1, 1) ***\n"; | |
| print_time( test<std::vector, member_variable_object_t>, 1, 1); | |
| std::cout << "\n === std::vector<member_variable_object_t> ===\n"; | |
| print_time( test<std::vector, member_variable_object_t>, number_of_steps, number_of_objects ); | |
| std::cout << "\n === std::list<member_variable_object_t> ===\n"; | |
| print_time( test<std::list, member_variable_object_t>, number_of_steps, number_of_objects ); | |
| std::cout << "\n === std::forward_list<member_variable_object_t> ===\n"; | |
| print_time( test<std::forward_list, member_variable_object_t>, number_of_steps, number_of_objects ); | |
| std::cout << "\n === std::vector<map_string_any_object_t<>> ===\n"; | |
| print_time( test<std::vector, map_string_any_object_t<>>, number_of_steps, number_of_objects ); | |
| std::cout << "\n === std::list<map_string_any_object_t<>> ===\n"; | |
| print_time( test<std::list, map_string_any_object_t<>>, number_of_steps, number_of_objects ); | |
| std::cout << "\n === std::forward_list<map_string_any_object_t<>> ===\n"; | |
| print_time( test<std::forward_list, map_string_any_object_t<>>, number_of_steps, number_of_objects ); | |
| std::cout << "\n === std::vector<map_string_any_object_t<std::unordered_map<std::string, boost::any>>> ===\n"; | |
| print_time( test<std::vector, map_string_any_object_t<std::unordered_map<std::string, boost::any>>>, number_of_steps, number_of_objects ); | |
| std::cout << "\n === std::list<map_string_any_object_t<std::unordered_map<std::string, boost::any>>> ===\n"; | |
| print_time( test<std::list, map_string_any_object_t<std::unordered_map<std::string, boost::any>>>, number_of_steps, number_of_objects ); | |
| std::cout << "\n === std::forward_list<map_string_any_object_t<std::unordered_map<std::string, boost::any>>> ===\n"; | |
| print_time( test<std::forward_list, map_string_any_object_t<std::unordered_map<std::string, boost::any>>>, number_of_steps, number_of_objects ); | |
| std::cout << "\n === std::vector<map_string_any_object_t<ptree_object_t> ===\n"; | |
| print_time( test<std::vector, ptree_object_t>, number_of_steps, number_of_objects ); | |
| std::cout << "\n === std::list<map_string_any_object_t<ptree_object_t> ===\n"; | |
| print_time( test<std::list, ptree_object_t>, number_of_steps, number_of_objects ); | |
| std::cout << "\n === std::forward_list<ptree_object_t> ===\n"; | |
| print_time( test<std::forward_list, ptree_object_t>, number_of_steps, number_of_objects ); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| *** property_benchmark *** | |
| usage: ./a.out [number_of_steps] [number_of_objects] | |
| defaults are: 1000, 1000 | |
| this program benchmarks: | |
| basic Newton's Equation of motion with Eular's method using: | |
| 1. objects container types { std::vector, std::list, std::forward_list } | |
| 2. object owned property types { basic member variable, boost::property_tree::ptree } | |
| number_of_steps : 1000 | |
| number_of_objects: 1000 | |
| *** test running std::vector<basic_object_t>(1, 1) *** | |
| normalized sum of positions(initial): -0.337 -0.336 -0.879 | |
| normalized sum of positions(final) : -0.310 -0.361 -0.879 | |
| time: 107.10 [us] | |
| === std::vector<member_variable_object_t> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 780.61 [ms] | |
| === std::list<member_variable_object_t> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 774.97 [ms] | |
| === std::forward_list<member_variable_object_t> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 770.73 [ms] | |
| === std::vector<map_string_any_object_t<>> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 1390.85 [ms] | |
| === std::list<map_string_any_object_t<>> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 1402.11 [ms] | |
| === std::forward_list<map_string_any_object_t<>> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 1416.99 [ms] | |
| === std::vector<map_string_any_object_t<std::unordered_map<std::string, boost::any>>> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 1447.93 [ms] | |
| === std::list<map_string_any_object_t<std::unordered_map<std::string, boost::any>>> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 1412.33 [ms] | |
| === std::forward_list<map_string_any_object_t<std::unordered_map<std::string, boost::any>>> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 1453.10 [ms] | |
| === std::vector<map_string_any_object_t<ptree_object_t> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 48.37 [sec.] | |
| === std::list<map_string_any_object_t<ptree_object_t> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 48.76 [sec.] | |
| === std::forward_list<ptree_object_t> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 48.00 [sec.] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| *** property_benchmark *** | |
| usage: ./a.out [number_of_steps] [number_of_objects] | |
| defaults are: 1000, 1000 | |
| this program benchmarks: | |
| basic Newton's Equation of motion with Eular's method using: | |
| 1. objects container types { std::vector, std::list, std::forward_list } | |
| 2. object owned property types { basic member variable, boost::property_tree::ptree } | |
| number_of_steps : 1000 | |
| number_of_objects: 1000 | |
| *** test running std::vector<basic_object_t>(1, 1) *** | |
| normalized sum of positions(initial): -0.337 -0.336 -0.879 | |
| normalized sum of positions(final) : -0.310 -0.361 -0.879 | |
| time: 81.43 [us] | |
| === std::vector<member_variable_object_t> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 489.11 [ms] | |
| === std::list<member_variable_object_t> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 496.42 [ms] | |
| === std::forward_list<member_variable_object_t> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 501.26 [ms] | |
| === std::vector<map_string_any_object_t<>> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 789.39 [ms] | |
| === std::list<map_string_any_object_t<>> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 772.43 [ms] | |
| === std::forward_list<map_string_any_object_t<>> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 782.61 [ms] | |
| === std::vector<map_string_any_object_t<std::unordered_map<std::string, boost::any>>> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 755.05 [ms] | |
| === std::list<map_string_any_object_t<std::unordered_map<std::string, boost::any>>> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 762.71 [ms] | |
| === std::forward_list<map_string_any_object_t<std::unordered_map<std::string, boost::any>>> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 761.94 [ms] | |
| === std::vector<map_string_any_object_t<ptree_object_t> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 26.82 [sec.] | |
| === std::list<map_string_any_object_t<ptree_object_t> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 27.05 [sec.] | |
| === std::forward_list<ptree_object_t> === | |
| normalized sum of positions(initial): -0.562 -0.600 -0.570 | |
| normalized sum of positions(final) : -0.431 -0.754 -0.495 | |
| time: 26.64 [sec.] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment