SHOW:
|
|
- or go back to the newest paste.
| 1 | /** | |
| 2 | * Author: F. Philipp | |
| 3 | * | |
| 4 | * Translation of | |
| 5 | * https://benchmarksgame.alioth.debian.org/u64q/program.php?test=mandelbrot&lang=rust&id=4 | |
| 6 | * with minor changes | |
| 7 | * | |
| 8 | * Contains a bug resulting in slightly different results | |
| 9 | */ | |
| 10 | ||
| 11 | - | #include <array> |
| 11 | + | #include <Eigen/Dense> |
| 12 | - | // using std::array |
| 12 | + | |
| 13 | ||
| 14 | #include <vector> | |
| 15 | - | #include <tuple> |
| 15 | + | |
| 16 | - | // using std::tuple |
| 16 | + | |
| 17 | // using std::stoi | |
| 18 | #include <iostream> | |
| 19 | // using std::cout | |
| 20 | #include <algorithm> | |
| 21 | // using std::transform | |
| 22 | - | // using std::transform, std::all_of |
| 22 | + | |
| 23 | - | #include <functional> |
| 23 | + | |
| 24 | - | // using std::bind, std::placeholders, std::multiplies, std::plus, std::minus |
| 24 | + | |
| 25 | ||
| 26 | namespace {
| |
| 27 | ||
| 28 | constexpr int MAX_ITER = 50; | |
| 29 | constexpr int VLEN = CHAR_BIT; | |
| 30 | using double_t = double; | |
| 31 | ||
| 32 | using Vecf64 = Eigen::Array<double_t, VLEN, 1>; | |
| 33 | - | typedef double double_t; |
| 33 | + | |
| 34 | template<class T> | |
| 35 | - | struct Vecf64 |
| 35 | + | using vector = std::vector<T, Eigen::aligned_allocator<T> >; |
| 36 | ||
| 37 | - | using array_type = std::array<double_t, VLEN>; |
| 37 | + | |
| 38 | - | array_type array; |
| 38 | + | |
| 39 | Vecf64 cr, cr2; | |
| 40 | - | Vecf64() = default; |
| 40 | + | |
| 41 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW | |
| 42 | - | explicit Vecf64(double_t s) noexcept |
| 42 | + | |
| 43 | - | { array.fill(s); }
|
| 43 | + | |
| 44 | class Mandelbrot8 | |
| 45 | - | Vecf64& operator=(const Vecf64&) = default; |
| 45 | + | |
| 46 | Vecf64 zr, zi, tr, ti, cr; | |
| 47 | - | Vecf64& operator=(double_t s) noexcept |
| 47 | + | |
| 48 | ||
| 49 | - | array.fill(s); |
| 49 | + | |
| 50 | - | return *this; |
| 50 | + | |
| 51 | for(int i = 0; i < iterations; ++i) {
| |
| 52 | - | double_t& operator[](int idx) noexcept |
| 52 | + | |
| 53 | - | { return array[idx]; }
|
| 53 | + | |
| 54 | tr = zr.square(); | |
| 55 | - | double_t operator[](int idx) const noexcept |
| 55 | + | |
| 56 | - | { return array[idx]; }
|
| 56 | + | |
| 57 | } | |
| 58 | - | template<class BinaryFunctor> |
| 58 | + | |
| 59 | - | Vecf64& inplace_transform(const Vecf64& o, BinaryFunctor f) |
| 59 | + | |
| 60 | return ((tr + ti) > 4).all(); | |
| 61 | - | array_type::iterator first = array.begin(); |
| 61 | + | |
| 62 | - | std::transform(first, array.end(), o.array.begin(), first, f); |
| 62 | + | |
| 63 | - | return *this; |
| 63 | + | |
| 64 | const Vecf64 trti = tr + ti; | |
| 65 | - | template<class BinaryFunctor> |
| 65 | + | |
| 66 | - | Vecf64 transform(const Vecf64& o, BinaryFunctor f) const |
| 66 | + | |
| 67 | if(trti[i] <= 4.) | |
| 68 | - | Vecf64 rtrn; |
| 68 | + | |
| 69 | - | std::transform(array.begin(), array.end(), o.array.begin(), |
| 69 | + | |
| 70 | - | rtrn.array.begin(), f); |
| 70 | + | |
| 71 | - | return rtrn; |
| 71 | + | |
| 72 | public: | |
| 73 | - | template<class UnaryFunctor> |
| 73 | + | EIGEN_MAKE_ALIGNED_OPERATOR_NEW |
| 74 | - | Vecf64& inplace_transform(UnaryFunctor f) |
| 74 | + | |
| 75 | explicit Mandelbrot8(double_t ci) noexcept | |
| 76 | - | array_type::iterator first = array.begin(); |
| 76 | + | |
| 77 | - | std::transform(first, array.end(), first, f); |
| 77 | + | |
| 78 | - | return *this; |
| 78 | + | |
| 79 | unsigned char operator()(const CrCr2Chunk& col_invariant) noexcept | |
| 80 | - | template<class UnaryFunctor> |
| 80 | + | |
| 81 | - | Vecf64 transform(UnaryFunctor f) const |
| 81 | + | |
| 82 | zi = ci; | |
| 83 | - | Vecf64 rtrn; |
| 83 | + | |
| 84 | - | std::transform(array.begin(), array.end(), rtrn.array.begin(), f); |
| 84 | + | |
| 85 | - | return rtrn; |
| 85 | + | |
| 86 | advance(4); | |
| 87 | constexpr int n = MAX_ITER / 5 - 1; | |
| 88 | - | Vecf64& operator*=(const Vecf64& o) noexcept |
| 88 | + | |
| 89 | - | { return inplace_transform(o, std::multiplies<double_t>{}); }
|
| 89 | + | |
| 90 | return 0; | |
| 91 | - | Vecf64 operator*(const Vecf64& o) const noexcept |
| 91 | + | |
| 92 | - | { return transform(o, std::multiplies<double_t>{}); }
|
| 92 | + | |
| 93 | return to_byte(); | |
| 94 | - | Vecf64& operator*=(double_t s) noexcept |
| 94 | + | |
| 95 | }; | |
| 96 | - | return inplace_transform(std::bind(std::multiplies<double_t>{},
|
| 96 | + | |
| 97 | - | std::placeholders::_1, s)); |
| 97 | + | vector<CrCr2Chunk> make_column_invariant(int bytes_per_line) |
| 98 | {
| |
| 99 | - | Vecf64 operator*(double_t s) const noexcept |
| 99 | + | |
| 100 | const double_t inv = 2. / pixels_per_line; | |
| 101 | - | return transform(std::bind(std::multiplies<double_t>{},
|
| 101 | + | vector<CrCr2Chunk> rtrn(bytes_per_line); |
| 102 | - | std::placeholders::_1, s)); |
| 102 | + | |
| 103 | for(int col_byte = 0; col_byte < bytes_per_line; ++col_byte) {
| |
| 104 | - | friend Vecf64 operator*(double_t left, const Vecf64& right) noexcept |
| 104 | + | |
| 105 | - | { return right * left; }
|
| 105 | + | |
| 106 | const int col = col_byte * VLEN + bit; | |
| 107 | - | Vecf64& operator+=(const Vecf64& o) noexcept |
| 107 | + | |
| 108 | - | { return inplace_transform(o, std::plus<double_t>{}); }
|
| 108 | + | |
| 109 | chunk.cr2 = chunk.cr.square(); | |
| 110 | - | Vecf64 operator+(const Vecf64& o) const noexcept |
| 110 | + | |
| 111 | - | { return transform(o, std::plus<double_t>{}); }
|
| 111 | + | |
| 112 | } | |
| 113 | - | Vecf64& operator+=(double_t s) noexcept |
| 113 | + | |
| 114 | std::vector<unsigned char> | |
| 115 | - | return inplace_transform(std::bind(std::plus<double_t>{},
|
| 115 | + | make_bitmap(const vector<CrCr2Chunk>& column_invariants) |
| 116 | - | std::placeholders::_1, s)); |
| 116 | + | |
| 117 | const int bytes_per_line = static_cast<int>(column_invariants.size()); | |
| 118 | - | Vecf64 operator+(double_t s) const noexcept |
| 118 | + | |
| 119 | const double_t inv = 2. / pixels_per_line; | |
| 120 | - | return transform(std::bind(std::plus<double_t>{},
|
| 120 | + | |
| 121 | - | std::placeholders::_1, s)); |
| 121 | + | |
| 122 | for(int row = 0; row < pixels_per_line; ++row) {
| |
| 123 | - | friend Vecf64 operator+(double_t left, const Vecf64& right) noexcept |
| 123 | + | |
| 124 | - | { return right + left; }
|
| 124 | + | |
| 125 | std::transform(column_invariants.begin(), column_invariants.end(), | |
| 126 | - | Vecf64& operator-=(const Vecf64& o) noexcept |
| 126 | + | |
| 127 | - | { return inplace_transform(o, std::minus<double_t>{}); }
|
| 127 | + | |
| 128 | } | |
| 129 | - | Vecf64 operator-(const Vecf64& o) const noexcept |
| 129 | + | |
| 130 | - | { return transform(o, std::minus<double_t>{}); }
|
| 130 | + | |
| 131 | void print_pbm(const std::vector<unsigned char>& bitmap, | |
| 132 | - | Vecf64& operator-=(double_t s) noexcept |
| 132 | + | |
| 133 | std::ostream& binary_output) | |
| 134 | - | return inplace_transform(std::bind(std::minus<double_t>{},
|
| 134 | + | |
| 135 | - | std::placeholders::_1, s)); |
| 135 | + | |
| 136 | << ' ' << pixels_per_line | |
| 137 | - | Vecf64 operator-(double_t s) const noexcept |
| 137 | + | |
| 138 | binary_output.write(reinterpret_cast<const char*>(bitmap.data()), | |
| 139 | - | return transform(std::bind(std::minus<double_t>{},
|
| 139 | + | |
| 140 | - | std::placeholders::_1, s)); |
| 140 | + | |
| 141 | } | |
| 142 | - | friend Vecf64 operator-(double_t left, const Vecf64& right) noexcept |
| 142 | + | |
| 143 | ||
| 144 | - | return right.transform(std::bind(std::minus<double_t>{},
|
| 144 | + | |
| 145 | - | left, std::placeholders::_1)); |
| 145 | + | |
| 146 | /* number of pixels in each dimension */ | |
| 147 | - | Vecf64& inplace_square() noexcept |
| 147 | + | |
| 148 | if(argc > 1) | |
| 149 | - | return inplace_transform(std::bind(std::multiplies<double_t>{},
|
| 149 | + | |
| 150 | - | std::placeholders::_1, |
| 150 | + | |
| 151 | - | std::placeholders::_1)); |
| 151 | + | |
| 152 | const vector<CrCr2Chunk> column_invariants = | |
| 153 | - | Vecf64 square() const noexcept |
| 153 | + | |
| 154 | const std::vector<unsigned char> bitmap = make_bitmap(column_invariants); | |
| 155 | - | return transform(std::bind(std::multiplies<double_t>{},
|
| 155 | + | |
| 156 | - | std::placeholders::_1, |
| 156 | + |