<commit_before>#pragma once

#include <array>

namespace yunomi {
    namespace core {
        class Select8Bit {
        public:
            constexpr
            Select8Bit() {}

            constexpr
            uint8_t operator()(uint8_t value, uint8_t i) const {
                return select_impl(value, i, 0, 0);
            }

        private:
            constexpr
            uint8_t select_impl(uint8_t value, size_t i, uint8_t done, uint8_t popcount) const {
                return done >= 8?
                       done + popcount
                                : (((value >> done) & 0x1ULL) == 1?
                                   (i == 0? done : select_impl(value, i - 1, done + 1, popcount + 1))
                                                                  : select_impl(value, i, done + 1, popcount));
            }
        };

        class SelectDictImplValue {
        public:
            constexpr
            SelectDictImplValue(uint8_t value)
                    : dict_{
                    Select8Bit()(value, 0),
                    Select8Bit()(value, 1),
                    Select8Bit()(value, 2),
                    Select8Bit()(value, 3),
                    Select8Bit()(value, 4),
                    Select8Bit()(value, 5),
                    Select8Bit()(value, 6),
                    Select8Bit()(value, 7)
            }

            {}

            constexpr uint8_t operator[](uint8_t i) const {
                return dict_[i];
            }

        private:
            const uint8_t dict_[8];
        };

        class SelectDictImpl {
        public:
            constexpr
            SelectDictImpl():
                    dict_{
                            SelectDictImplValue(0),
                            SelectDictImplValue(1),
                            SelectDictImplValue(2),
                            SelectDictImplValue(3),
                            SelectDictImplValue(4),
                            SelectDictImplValue(5),
                            SelectDictImplValue(6),
                            SelectDictImplValue(7),
                            SelectDictImplValue(8),
                            SelectDictImplValue(9),
                            SelectDictImplValue(10),
                            SelectDictImplValue(11),
                            SelectDictImplValue(12),
                            SelectDictImplValue(13),
                            SelectDictImplValue(14),
                            SelectDictImplValue(15),
                            SelectDictImplValue(16),
                            SelectDictImplValue(17),
                            SelectDictImplValue(18),
                            SelectDictImplValue(19),
                            SelectDictImplValue(20),
                            SelectDictImplValue(21),
                            SelectDictImplValue(22),
                            SelectDictImplValue(23),
                            SelectDictImplValue(24),
                            SelectDictImplValue(25),
                            SelectDictImplValue(26),
                            SelectDictImplValue(27),
                            SelectDictImplValue(28),
                            SelectDictImplValue(29),
                            SelectDictImplValue(30),
                            SelectDictImplValue(31),
                            SelectDictImplValue(32),
                            SelectDictImplValue(33),
                            SelectDictImplValue(34),
                            SelectDictImplValue(35),
                            SelectDictImplValue(36),
                            SelectDictImplValue(37),
                            SelectDictImplValue(38),
                            SelectDictImplValue(39),
                            SelectDictImplValue(40),
                            SelectDictImplValue(41),
                            SelectDictImplValue(42),
                            SelectDictImplValue(43),
                            SelectDictImplValue(44),
                            SelectDictImplValue(45),
                            SelectDictImplValue(46),
                            SelectDictImplValue(47),
                            SelectDictImplValue(48),
                            SelectDictImplValue(49),
                            SelectDictImplValue(50),
                            SelectDictImplValue(51),
                            SelectDictImplValue(52),
                            SelectDictImplValue(53),
                            SelectDictImplValue(54),
                            SelectDictImplValue(55),
                            SelectDictImplValue(56),
                            SelectDictImplValue(57),
                            SelectDictImplValue(58),
                            SelectDictImplValue(59),
                            SelectDictImplValue(60),
                            SelectDictImplValue(61),
                            SelectDictImplValue(62),
                            SelectDictImplValue(63),
                            SelectDictImplValue(64),
                            SelectDictImplValue(65),
                            SelectDictImplValue(66),
                            SelectDictImplValue(67),
                            SelectDictImplValue(68),
                            SelectDictImplValue(69),
                            SelectDictImplValue(70),
                            SelectDictImplValue(71),
                            SelectDictImplValue(72),
                            SelectDictImplValue(73),
                            SelectDictImplValue(74),
                            SelectDictImplValue(75),
                            SelectDictImplValue(76),
                            SelectDictImplValue(77),
                            SelectDictImplValue(78),
                            SelectDictImplValue(79),
                            SelectDictImplValue(80),
                            SelectDictImplValue(81),
                            SelectDictImplValue(82),
                            SelectDictImplValue(83),
                            SelectDictImplValue(84),
                            SelectDictImplValue(85),
                            SelectDictImplValue(86),
                            SelectDictImplValue(87),
                            SelectDictImplValue(88),
                            SelectDictImplValue(89),
                            SelectDictImplValue(90),
                            SelectDictImplValue(91),
                            SelectDictImplValue(92),
                            SelectDictImplValue(93),
                            SelectDictImplValue(94),
                            SelectDictImplValue(95),
                            SelectDictImplValue(96),
                            SelectDictImplValue(97),
                            SelectDictImplValue(98),
                            SelectDictImplValue(99),
                            SelectDictImplValue(100),
                            SelectDictImplValue(101),
                            SelectDictImplValue(102),
                            SelectDictImplValue(103),
                            SelectDictImplValue(104),
                            SelectDictImplValue(105),
                            SelectDictImplValue(106),
                            SelectDictImplValue(107),
                            SelectDictImplValue(108),
                            SelectDictImplValue(109),
                            SelectDictImplValue(110),
                            SelectDictImplValue(111),
                            SelectDictImplValue(112),
                            SelectDictImplValue(113),
                            SelectDictImplValue(114),
                            SelectDictImplValue(115),
                            SelectDictImplValue(116),
                            SelectDictImplValue(117),
                            SelectDictImplValue(118),
                            SelectDictImplValue(119),
                            SelectDictImplValue(120),
                            SelectDictImplValue(121),
                            SelectDictImplValue(122),
                            SelectDictImplValue(123),
                            SelectDictImplValue(124),
                            SelectDictImplValue(125),
                            SelectDictImplValue(126),
                            SelectDictImplValue(127),
                            SelectDictImplValue(128),
                            SelectDictImplValue(129),
                            SelectDictImplValue(130),
                            SelectDictImplValue(131),
                            SelectDictImplValue(132),
                            SelectDictImplValue(133),
                            SelectDictImplValue(134),
                            SelectDictImplValue(135),
                            SelectDictImplValue(136),
                            SelectDictImplValue(137),
                            SelectDictImplValue(138),
                            SelectDictImplValue(139),
                            SelectDictImplValue(140),
                            SelectDictImplValue(141),
                            SelectDictImplValue(142),
                            SelectDictImplValue(143),
                            SelectDictImplValue(144),
                            SelectDictImplValue(145),
                            SelectDictImplValue(146),
                            SelectDictImplValue(147),
                            SelectDictImplValue(148),
                            SelectDictImplValue(149),
                            SelectDictImplValue(150),
                            SelectDictImplValue(151),
                            SelectDictImplValue(152),
                            SelectDictImplValue(153),
                            SelectDictImplValue(154),
                            SelectDictImplValue(155),
                            SelectDictImplValue(156),
                            SelectDictImplValue(157),
                            SelectDictImplValue(158),
                            SelectDictImplValue(159),
                            SelectDictImplValue(160),
                            SelectDictImplValue(161),
                            SelectDictImplValue(162),
                            SelectDictImplValue(163),
                            SelectDictImplValue(164),
                            SelectDictImplValue(165),
                            SelectDictImplValue(166),
                            SelectDictImplValue(167),
                            SelectDictImplValue(168),
                            SelectDictImplValue(169),
                            SelectDictImplValue(170),
                            SelectDictImplValue(171),
                            SelectDictImplValue(172),
                            SelectDictImplValue(173),
                            SelectDictImplValue(174),
                            SelectDictImplValue(175),
                            SelectDictImplValue(176),
                            SelectDictImplValue(177),
                            SelectDictImplValue(178),
                            SelectDictImplValue(179),
                            SelectDictImplValue(180),
                            SelectDictImplValue(181),
                            SelectDictImplValue(182),
                            SelectDictImplValue(183),
                            SelectDictImplValue(184),
                            SelectDictImplValue(185),
                            SelectDictImplValue(186),
                            SelectDictImplValue(187),
                            SelectDictImplValue(188),
                            SelectDictImplValue(189),
                            SelectDictImplValue(190),
                            SelectDictImplValue(191),
                            SelectDictImplValue(192),
                            SelectDictImplValue(193),
                            SelectDictImplValue(194),
                            SelectDictImplValue(195),
                            SelectDictImplValue(196),
                            SelectDictImplValue(197),
                            SelectDictImplValue(198),
                            SelectDictImplValue(199),
                            SelectDictImplValue(200),
                            SelectDictImplValue(201),
                            SelectDictImplValue(202),
                            SelectDictImplValue(203),
                            SelectDictImplValue(204),
                            SelectDictImplValue(205),
                            SelectDictImplValue(206),
                            SelectDictImplValue(207),
                            SelectDictImplValue(208),
                            SelectDictImplValue(209),
                            SelectDictImplValue(210),
                            SelectDictImplValue(211),
                            SelectDictImplValue(212),
                            SelectDictImplValue(213),
                            SelectDictImplValue(214),
                            SelectDictImplValue(215),
                            SelectDictImplValue(216),
                            SelectDictImplValue(217),
                            SelectDictImplValue(218),
                            SelectDictImplValue(219),
                            SelectDictImplValue(220),
                            SelectDictImplValue(221),
                            SelectDictImplValue(222),
                            SelectDictImplValue(223),
                            SelectDictImplValue(224),
                            SelectDictImplValue(225),
                            SelectDictImplValue(226),
                            SelectDictImplValue(227),
                            SelectDictImplValue(228),
                            SelectDictImplValue(229),
                            SelectDictImplValue(230),
                            SelectDictImplValue(231),
                            SelectDictImplValue(232),
                            SelectDictImplValue(233),
                            SelectDictImplValue(234),
                            SelectDictImplValue(235),
                            SelectDictImplValue(236),
                            SelectDictImplValue(237),
                            SelectDictImplValue(238),
                            SelectDictImplValue(239),
                            SelectDictImplValue(240),
                            SelectDictImplValue(241),
                            SelectDictImplValue(242),
                            SelectDictImplValue(243),
                            SelectDictImplValue(244),
                            SelectDictImplValue(245),
                            SelectDictImplValue(246),
                            SelectDictImplValue(247),
                            SelectDictImplValue(248),
                            SelectDictImplValue(249),
                            SelectDictImplValue(250),
                            SelectDictImplValue(251),
                            SelectDictImplValue(252),
                            SelectDictImplValue(253),
                            SelectDictImplValue(254),
                            SelectDictImplValue(255)
                    } {}

            constexpr
            const SelectDictImplValue &operator[](uint8_t value) const {
                return dict_[value];
            }

        private:
            const SelectDictImplValue dict_[256];
        };

        class SelectDict{
        public:
            constexpr
            SelectDict(){}

            constexpr
            uint8_t operator()(uint8_t value, uint8_t i) const {
                return dict_[value][i];
            }

        private:
            SelectDictImpl dict_;
        };

        class RegisterSuccinct {
        public:
            RegisterSuccinct(uint64_t value): value_(value){}

            uint8_t select(uint8_t i) const {
                constexpr SelectDict select;
                uint64_t value = value_;
                uint8_t sel = 0;
                for(uint8_t j = 0; j < 8; j++){
                    uint8_t byte = (uint8_t)value;
                    uint8_t byte_sel = select(byte, i);
                    if(byte_sel < 8){
                        // found i-th 1.
                        return sel + byte_sel;
                    }else{
                        i = i - (byte_sel - 8);
                        sel += 8;
                        value = value >> 8;
                    }
                }
                // not found
                return not_found();
            }

            constexpr static
            uint8_t not_found() {
                return 64;
            }

        private:
            uint64_t value_;
        };

    }
}
<commit_msg>Add documents for succinct.hpp.<commit_after>#pragma once

#include <array>

namespace yunomi {
    namespace core {

        /**
         * @brief an implementation of a select function for 8bits value
         * @details
         * This class is an implementation of a select function.
         * `select` is one of the well known function, especially in the field "succinct data structure".
         *
         * function `select(value, i)` is defined as:
         *
         *     select(value, i) = \argmax_k rank(k) == i,
         *
         * where:
         *
         *     rank(value, i) = \sum_{j = 0}^{i - 1} value[j:j + 1].
         *
         * On this implementation, `value` is restricted up to 8bits value (0 <= `value` < 256)
         *
         */
        class Select8Bit {
        public:
            constexpr
            Select8Bit() {}

            /**
             * @brief execute the select operation for given input values
             * @param[in] value any unsigned value up to 8bits
             * @param[in] i specify the number that you want to get the index of i-th 1
             * @return uint8_t
             * Index of digits that the given i-th one is found.
             * If i-th one is not found, it returns larger than 8.
             */
            constexpr
            uint8_t operator()(uint8_t value, uint8_t i) const {
                return select_impl(value, i, 0, 0);
            }

        private:
            constexpr
            uint8_t select_impl(uint8_t value, size_t i, uint8_t done, uint8_t popcount) const {
                return done >= 8?
                       done + popcount
                                : (((value >> done) & 0x1ULL) == 1?
                                   (i == 0? done : select_impl(value, i - 1, done + 1, popcount + 1))
                                                                  : select_impl(value, i, done + 1, popcount));
            }
        };

        /**
         * @brief precomputed cache of `Select8Bit` results for a given value.
         */
        class SelectDictImplValue {
        public:
            /**
             * @brief constructor. calculate all patterns for the given `value`
             * @param value target value that need to be precomputed
             */
            constexpr
            SelectDictImplValue(uint8_t value)
                    : dict_{
                    Select8Bit()(value, 0),
                    Select8Bit()(value, 1),
                    Select8Bit()(value, 2),
                    Select8Bit()(value, 3),
                    Select8Bit()(value, 4),
                    Select8Bit()(value, 5),
                    Select8Bit()(value, 6),
                    Select8Bit()(value, 7)
            }
            {}

            /**
             * @brief get a precomputed `select(value, i)` value
             * @param[in] i specify the number that you want to get the index of i-th 1
             * @return uint8_t index of digits that the given i-th one is found.
             * if i-th one is not found, it returns larger than 8.
             */
            constexpr uint8_t operator[](uint8_t i) const {
                return dict_[i];
            }

        private:
            const uint8_t dict_[8];
        };

        /**
         * @brief precomputed cache of `Select8Bit` results for any 8bits value
         */
        class SelectDictImpl {
        public:
            constexpr
            SelectDictImpl():
                    dict_{
                            SelectDictImplValue(0),
                            SelectDictImplValue(1),
                            SelectDictImplValue(2),
                            SelectDictImplValue(3),
                            SelectDictImplValue(4),
                            SelectDictImplValue(5),
                            SelectDictImplValue(6),
                            SelectDictImplValue(7),
                            SelectDictImplValue(8),
                            SelectDictImplValue(9),
                            SelectDictImplValue(10),
                            SelectDictImplValue(11),
                            SelectDictImplValue(12),
                            SelectDictImplValue(13),
                            SelectDictImplValue(14),
                            SelectDictImplValue(15),
                            SelectDictImplValue(16),
                            SelectDictImplValue(17),
                            SelectDictImplValue(18),
                            SelectDictImplValue(19),
                            SelectDictImplValue(20),
                            SelectDictImplValue(21),
                            SelectDictImplValue(22),
                            SelectDictImplValue(23),
                            SelectDictImplValue(24),
                            SelectDictImplValue(25),
                            SelectDictImplValue(26),
                            SelectDictImplValue(27),
                            SelectDictImplValue(28),
                            SelectDictImplValue(29),
                            SelectDictImplValue(30),
                            SelectDictImplValue(31),
                            SelectDictImplValue(32),
                            SelectDictImplValue(33),
                            SelectDictImplValue(34),
                            SelectDictImplValue(35),
                            SelectDictImplValue(36),
                            SelectDictImplValue(37),
                            SelectDictImplValue(38),
                            SelectDictImplValue(39),
                            SelectDictImplValue(40),
                            SelectDictImplValue(41),
                            SelectDictImplValue(42),
                            SelectDictImplValue(43),
                            SelectDictImplValue(44),
                            SelectDictImplValue(45),
                            SelectDictImplValue(46),
                            SelectDictImplValue(47),
                            SelectDictImplValue(48),
                            SelectDictImplValue(49),
                            SelectDictImplValue(50),
                            SelectDictImplValue(51),
                            SelectDictImplValue(52),
                            SelectDictImplValue(53),
                            SelectDictImplValue(54),
                            SelectDictImplValue(55),
                            SelectDictImplValue(56),
                            SelectDictImplValue(57),
                            SelectDictImplValue(58),
                            SelectDictImplValue(59),
                            SelectDictImplValue(60),
                            SelectDictImplValue(61),
                            SelectDictImplValue(62),
                            SelectDictImplValue(63),
                            SelectDictImplValue(64),
                            SelectDictImplValue(65),
                            SelectDictImplValue(66),
                            SelectDictImplValue(67),
                            SelectDictImplValue(68),
                            SelectDictImplValue(69),
                            SelectDictImplValue(70),
                            SelectDictImplValue(71),
                            SelectDictImplValue(72),
                            SelectDictImplValue(73),
                            SelectDictImplValue(74),
                            SelectDictImplValue(75),
                            SelectDictImplValue(76),
                            SelectDictImplValue(77),
                            SelectDictImplValue(78),
                            SelectDictImplValue(79),
                            SelectDictImplValue(80),
                            SelectDictImplValue(81),
                            SelectDictImplValue(82),
                            SelectDictImplValue(83),
                            SelectDictImplValue(84),
                            SelectDictImplValue(85),
                            SelectDictImplValue(86),
                            SelectDictImplValue(87),
                            SelectDictImplValue(88),
                            SelectDictImplValue(89),
                            SelectDictImplValue(90),
                            SelectDictImplValue(91),
                            SelectDictImplValue(92),
                            SelectDictImplValue(93),
                            SelectDictImplValue(94),
                            SelectDictImplValue(95),
                            SelectDictImplValue(96),
                            SelectDictImplValue(97),
                            SelectDictImplValue(98),
                            SelectDictImplValue(99),
                            SelectDictImplValue(100),
                            SelectDictImplValue(101),
                            SelectDictImplValue(102),
                            SelectDictImplValue(103),
                            SelectDictImplValue(104),
                            SelectDictImplValue(105),
                            SelectDictImplValue(106),
                            SelectDictImplValue(107),
                            SelectDictImplValue(108),
                            SelectDictImplValue(109),
                            SelectDictImplValue(110),
                            SelectDictImplValue(111),
                            SelectDictImplValue(112),
                            SelectDictImplValue(113),
                            SelectDictImplValue(114),
                            SelectDictImplValue(115),
                            SelectDictImplValue(116),
                            SelectDictImplValue(117),
                            SelectDictImplValue(118),
                            SelectDictImplValue(119),
                            SelectDictImplValue(120),
                            SelectDictImplValue(121),
                            SelectDictImplValue(122),
                            SelectDictImplValue(123),
                            SelectDictImplValue(124),
                            SelectDictImplValue(125),
                            SelectDictImplValue(126),
                            SelectDictImplValue(127),
                            SelectDictImplValue(128),
                            SelectDictImplValue(129),
                            SelectDictImplValue(130),
                            SelectDictImplValue(131),
                            SelectDictImplValue(132),
                            SelectDictImplValue(133),
                            SelectDictImplValue(134),
                            SelectDictImplValue(135),
                            SelectDictImplValue(136),
                            SelectDictImplValue(137),
                            SelectDictImplValue(138),
                            SelectDictImplValue(139),
                            SelectDictImplValue(140),
                            SelectDictImplValue(141),
                            SelectDictImplValue(142),
                            SelectDictImplValue(143),
                            SelectDictImplValue(144),
                            SelectDictImplValue(145),
                            SelectDictImplValue(146),
                            SelectDictImplValue(147),
                            SelectDictImplValue(148),
                            SelectDictImplValue(149),
                            SelectDictImplValue(150),
                            SelectDictImplValue(151),
                            SelectDictImplValue(152),
                            SelectDictImplValue(153),
                            SelectDictImplValue(154),
                            SelectDictImplValue(155),
                            SelectDictImplValue(156),
                            SelectDictImplValue(157),
                            SelectDictImplValue(158),
                            SelectDictImplValue(159),
                            SelectDictImplValue(160),
                            SelectDictImplValue(161),
                            SelectDictImplValue(162),
                            SelectDictImplValue(163),
                            SelectDictImplValue(164),
                            SelectDictImplValue(165),
                            SelectDictImplValue(166),
                            SelectDictImplValue(167),
                            SelectDictImplValue(168),
                            SelectDictImplValue(169),
                            SelectDictImplValue(170),
                            SelectDictImplValue(171),
                            SelectDictImplValue(172),
                            SelectDictImplValue(173),
                            SelectDictImplValue(174),
                            SelectDictImplValue(175),
                            SelectDictImplValue(176),
                            SelectDictImplValue(177),
                            SelectDictImplValue(178),
                            SelectDictImplValue(179),
                            SelectDictImplValue(180),
                            SelectDictImplValue(181),
                            SelectDictImplValue(182),
                            SelectDictImplValue(183),
                            SelectDictImplValue(184),
                            SelectDictImplValue(185),
                            SelectDictImplValue(186),
                            SelectDictImplValue(187),
                            SelectDictImplValue(188),
                            SelectDictImplValue(189),
                            SelectDictImplValue(190),
                            SelectDictImplValue(191),
                            SelectDictImplValue(192),
                            SelectDictImplValue(193),
                            SelectDictImplValue(194),
                            SelectDictImplValue(195),
                            SelectDictImplValue(196),
                            SelectDictImplValue(197),
                            SelectDictImplValue(198),
                            SelectDictImplValue(199),
                            SelectDictImplValue(200),
                            SelectDictImplValue(201),
                            SelectDictImplValue(202),
                            SelectDictImplValue(203),
                            SelectDictImplValue(204),
                            SelectDictImplValue(205),
                            SelectDictImplValue(206),
                            SelectDictImplValue(207),
                            SelectDictImplValue(208),
                            SelectDictImplValue(209),
                            SelectDictImplValue(210),
                            SelectDictImplValue(211),
                            SelectDictImplValue(212),
                            SelectDictImplValue(213),
                            SelectDictImplValue(214),
                            SelectDictImplValue(215),
                            SelectDictImplValue(216),
                            SelectDictImplValue(217),
                            SelectDictImplValue(218),
                            SelectDictImplValue(219),
                            SelectDictImplValue(220),
                            SelectDictImplValue(221),
                            SelectDictImplValue(222),
                            SelectDictImplValue(223),
                            SelectDictImplValue(224),
                            SelectDictImplValue(225),
                            SelectDictImplValue(226),
                            SelectDictImplValue(227),
                            SelectDictImplValue(228),
                            SelectDictImplValue(229),
                            SelectDictImplValue(230),
                            SelectDictImplValue(231),
                            SelectDictImplValue(232),
                            SelectDictImplValue(233),
                            SelectDictImplValue(234),
                            SelectDictImplValue(235),
                            SelectDictImplValue(236),
                            SelectDictImplValue(237),
                            SelectDictImplValue(238),
                            SelectDictImplValue(239),
                            SelectDictImplValue(240),
                            SelectDictImplValue(241),
                            SelectDictImplValue(242),
                            SelectDictImplValue(243),
                            SelectDictImplValue(244),
                            SelectDictImplValue(245),
                            SelectDictImplValue(246),
                            SelectDictImplValue(247),
                            SelectDictImplValue(248),
                            SelectDictImplValue(249),
                            SelectDictImplValue(250),
                            SelectDictImplValue(251),
                            SelectDictImplValue(252),
                            SelectDictImplValue(253),
                            SelectDictImplValue(254),
                            SelectDictImplValue(255)
                    } {}

            /**
             * @brief get a precomputed cache for given `value`
             * @param[in] value specify any unsigned value up to 8bits.
             * @return `SelectDictImpleValue&`
             * Precomputed cache for the given `value`.
             */
            constexpr
            const SelectDictImplValue &operator[](uint8_t value) const {
                return dict_[value];
            }

        private:
            const SelectDictImplValue dict_[256];
        };

        /**
         * @brief Precomputed cache for `Select8Bit`.
         */
        class SelectDict{
        public:
            constexpr
            SelectDict(){}

            /**
             * @brief lookup precomputed value.
             * @param[in] value any unsigned value up to 8bits
             * @param[in] i specify the number that you want to get the index of i-th 1
             * @return uint8_t
             * precomputed results of `Select8Bit()(value, i)`.
             * This is useful when `Select8Bit` seems to be slow.
             */
            constexpr
            uint8_t operator()(uint8_t value, uint8_t i) const {
                return dict_[value][i];
            }

        private:
            SelectDictImpl dict_;
        };

        /**
         *  @brief utility class for calculating select function for uint64_t value
         */
        class RegisterSuccinct {
        public:
            RegisterSuccinct(uint64_t value): value_(value){}

            /**
             * @brief calculate select function for `value_`
             */
            uint8_t select(uint8_t i) const {
                constexpr SelectDict select;
                uint64_t value = value_;
                uint8_t sel = 0;
                for(uint8_t j = 0; j < 8; j++){
                    uint8_t byte = (uint8_t)value;
                    uint8_t byte_sel = select(byte, i);
                    if(byte_sel < 8){
                        // found i-th 1.
                        return sel + byte_sel;
                    }else{
                        i = i - (byte_sel - 8);
                        sel += 8;
                        value = value >> 8;
                    }
                }
                // not found
                return not_found();
            }

            constexpr static
            uint8_t not_found() {
                return 64;
            }

        private:
            uint64_t value_;
        };

    }
}
<|endoftext|>


<commit_before>#include <gtest/gtest.h>

#include <typeindex>
#include <typeinfo>
#include <unordered_map>

#include "units.h"

using namespace distance_literals;

using testing::Test;
using testing::Types;
using testing::Values;
using testing::WithParamInterface;

namespace TestDistanceUnits
{
	template<typename T>
	class UnitCastTest : public Test
	{
	};

	TYPED_TEST_CASE_P(UnitCastTest);

#define UNITS_TYPE_COMBINE(T) std::tuple<T, units::nanometres>, \
std::tuple<T, units::micrometres>, \
std::tuple<T, units::millimetres>, \
std::tuple<T, units::centimetres>, \
std::tuple<T, units::decimetres>, \
std::tuple<T, units::metres>, \
std::tuple<T, units::kilometres>, \
std::tuple<T, units::thous>, \
std::tuple<T, units::inches>, \
std::tuple<T, units::links>, \
std::tuple<T, units::feet>, \
std::tuple<T, units::yards>, \
std::tuple<T, units::rods>, \
std::tuple<T, units::chains>, \
std::tuple<T, units::furlongs>, \
std::tuple<T, units::miles>, \
std::tuple<T, units::leagues>, \
std::tuple<T, units::fathoms>, \
std::tuple<T, units::cables>, \
std::tuple<T, units::nautical_miles>

	TYPED_TEST_P(UnitCastTest, UnitCast_WhenConvertedToCompatibleType_WillConvertBackWithoutPrecisionLoss)
	{
		using test_type = typename std::tuple_element_t<0, TypeParam>;
		using convertible_type = typename std::tuple_element_t<1, TypeParam>;

		convertible_type conversion = units::unit_cast<convertible_type>(test_type{ 1 });
		test_type result = units::unit_cast<test_type>(conversion);

		EXPECT_EQ(test_type{ 1 }, result);
	}

	// Metric
	using NanometresTuple = Types<UNITS_TYPE_COMBINE(units::nanometres)>;
	using MicrometresTuple = Types<UNITS_TYPE_COMBINE(units::micrometres)>;
	using MillimetresTuple = Types<UNITS_TYPE_COMBINE(units::millimetres)>;
	using CentimetresTuple = Types<UNITS_TYPE_COMBINE(units::centimetres)>;
	using DecimetresTuple = Types<UNITS_TYPE_COMBINE(units::decimetres)>;
	using MetresTuple = Types<UNITS_TYPE_COMBINE(units::metres)>;
	using KilometresTuple = Types<UNITS_TYPE_COMBINE(units::kilometres)>;

	// Imperial
	using ThousTuple = Types<UNITS_TYPE_COMBINE(units::thous)>;
	using InchesTuple = Types<UNITS_TYPE_COMBINE(units::inches)>;
	using LinksTuple = Types<UNITS_TYPE_COMBINE(units::links)>;
	using FeetTuple = Types<UNITS_TYPE_COMBINE(units::feet)>;
	using YardsTuple = Types<UNITS_TYPE_COMBINE(units::yards)>;
	using RodsTuple = Types<UNITS_TYPE_COMBINE(units::rods)>;
	using ChainsTuple = Types<UNITS_TYPE_COMBINE(units::chains)>;
	using FurlongsTuple = Types<UNITS_TYPE_COMBINE(units::furlongs)>;
	using MilesTuple = Types<UNITS_TYPE_COMBINE(units::miles)>;
	using LeaguesTuple = Types<UNITS_TYPE_COMBINE(units::leagues)>;

	// Maritime
	using FathomsTuple = Types<UNITS_TYPE_COMBINE(units::fathoms)>;
	using CablesTuple = Types<UNITS_TYPE_COMBINE(units::cables)>;
	using NauticalMilesTuple = Types<UNITS_TYPE_COMBINE(units::nautical_miles)>;

#undef UNITS_TYPE_COMBINE

	REGISTER_TYPED_TEST_CASE_P(UnitCastTest,
							   UnitCast_WhenConvertedToCompatibleType_WillConvertBackWithoutPrecisionLoss);

	INSTANTIATE_TYPED_TEST_CASE_P(Nanometres, UnitCastTest, NanometresTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Micrometres, UnitCastTest, MicrometresTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Millimetres, UnitCastTest, MillimetresTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Centimetres, UnitCastTest, CentimetresTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(DeciMetres, UnitCastTest, DecimetresTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Metres, UnitCastTest, MetresTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Kilometres, UnitCastTest, KilometresTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Thous, UnitCastTest, ThousTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Inches, UnitCastTest, InchesTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Links, UnitCastTest, LinksTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Feet, UnitCastTest, FeetTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Yards, UnitCastTest, YardsTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Rods, UnitCastTest, RodsTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Chains, UnitCastTest, ChainsTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Furlongs, UnitCastTest, FurlongsTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Miles, UnitCastTest, MilesTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Leagues, UnitCastTest, LeaguesTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Fathoms, UnitCastTest, FathomsTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Cables, UnitCastTest, CablesTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(NauticalMiles, UnitCastTest, NauticalMilesTuple);

	template <typename T>
	class BritishVsAmericanSpellingTest : public Test
	{
	};

	TYPED_TEST_CASE_P(BritishVsAmericanSpellingTest);

	TYPED_TEST_P(BritishVsAmericanSpellingTest, EitherSpellingYieldsSameType)
	{
		constexpr bool is_same = std::is_same<typename std::tuple_element<0, TypeParam>::type,
		                                      typename std::tuple_element<1, TypeParam>::type>::value;
		EXPECT_TRUE(is_same);
	}

	using BritishVsAmericanSpellingTuple = Types<std::tuple<units::nanometres, units::nanometers>,
	                                             std::tuple<units::micrometres, units::micrometers>,
	                                             std::tuple<units::millimetres, units::millimeters>,
	                                             std::tuple<units::centimetres, units::centimeters>,
	                                             std::tuple<units::decimetres, units::decimeters>,
	                                             std::tuple<units::metres, units::meters>,
	                                             std::tuple<units::kilometres, units::kilometers>>;

	REGISTER_TYPED_TEST_CASE_P(BritishVsAmericanSpellingTest, EitherSpellingYieldsSameType);

	INSTANTIATE_TYPED_TEST_CASE_P(BritishVsAmericanSpelling,
	                              BritishVsAmericanSpellingTest,
	                              BritishVsAmericanSpellingTuple);

	template <typename T>
	class LiteralsTest : public Test
	{
	};

	TYPED_TEST_CASE_P(LiteralsTest);

	TYPED_TEST_P(LiteralsTest, LiteralGeneratesCorrectType)
	{
		using expected_type    = typename std::tuple_element<0, TypeParam>::type;
		using actual_type      = typename std::tuple_element<1, TypeParam>::type;
		constexpr auto is_same = std::is_same<expected_type, actual_type>::value;
		EXPECT_TRUE(is_same) << "Incompatible types";
	}

	using MetricDistanceLiteralsTuple = Types<std::tuple<units::nanometres, decltype(1_nm)>,
	                                          std::tuple<units::micrometres, decltype(1_um)>,
	                                          std::tuple<units::millimetres, decltype(1_mm)>,
	                                          std::tuple<units::centimetres, decltype(1_cm)>,
	                                          std::tuple<units::metres, decltype(1_m)>,
	                                          std::tuple<units::kilometres, decltype(1_km)>>;

	using ImperialDistanceLiteralsTuple = Types<std::tuple<units::inches, decltype(1_in)>,
	                                            std::tuple<units::feet, decltype(1_ft)>,
	                                            std::tuple<units::yards, decltype(1_yd)>,
	                                            std::tuple<units::chains, decltype(1_ch)>,
	                                            std::tuple<units::furlongs, decltype(1_fur)>,
	                                            std::tuple<units::miles, decltype(1_mi)>,
	                                            std::tuple<units::leagues, decltype(1_lea)>,
	                                            std::tuple<units::thous, decltype(1_th)>>;

	using MaritimeDistanceLiteralsTuple = Types<std::tuple<units::fathoms, decltype(1_ftm)>,
	                                            std::tuple<units::cables, decltype(1_cb)>,
	                                            std::tuple<units::nautical_miles, decltype(1_NM)>,
	                                            std::tuple<units::nautical_miles, decltype(1_nmi)>>;

	using AstronomicalUnitsDistanceLiteralsTuple = Types<std::tuple<units::earth_radii, decltype(1_R)>,
	                                                     std::tuple<units::lunar_distances, decltype(1_LD)>,
	                                                     std::tuple<units::astronimical_units, decltype(1_AU)>,
	                                                     std::tuple<units::light_years, decltype(1_ly)>,
	                                                     std::tuple<units::parsecs, decltype(1_pc)>>;

	REGISTER_TYPED_TEST_CASE_P(LiteralsTest, LiteralGeneratesCorrectType);

	INSTANTIATE_TYPED_TEST_CASE_P(MetricDistance, LiteralsTest, MetricDistanceLiteralsTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(ImperialDistance, LiteralsTest, ImperialDistanceLiteralsTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(MaritimeDistance, LiteralsTest, MaritimeDistanceLiteralsTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(AstronomicalUnitsDistance, LiteralsTest, AstronomicalUnitsDistanceLiteralsTuple);
}
<commit_msg>Fix formatting...<commit_after>#include <gtest/gtest.h>

#include <typeindex>
#include <typeinfo>
#include <unordered_map>

#include "units.h"

using namespace distance_literals;

using testing::Test;
using testing::Types;
using testing::Values;
using testing::WithParamInterface;

namespace TestDistanceUnits
{
	template<typename T>
	class UnitCastTest : public Test
	{
	};

	TYPED_TEST_CASE_P(UnitCastTest);

#define UNITS_TYPE_COMBINE(T) \
std::tuple<T, units::nanometres>, \
std::tuple<T, units::micrometres>, \
std::tuple<T, units::millimetres>, \
std::tuple<T, units::centimetres>, \
std::tuple<T, units::decimetres>, \
std::tuple<T, units::metres>, \
std::tuple<T, units::kilometres>, \
std::tuple<T, units::thous>, \
std::tuple<T, units::inches>, \
std::tuple<T, units::links>, \
std::tuple<T, units::feet>, \
std::tuple<T, units::yards>, \
std::tuple<T, units::rods>, \
std::tuple<T, units::chains>, \
std::tuple<T, units::furlongs>, \
std::tuple<T, units::miles>, \
std::tuple<T, units::leagues>, \
std::tuple<T, units::fathoms>, \
std::tuple<T, units::cables>, \
std::tuple<T, units::nautical_miles>

	TYPED_TEST_P(UnitCastTest, UnitCast_WhenConvertedToCompatibleType_WillConvertBackWithoutPrecisionLoss)
	{
		using test_type = typename std::tuple_element_t<0, TypeParam>;
		using convertible_type = typename std::tuple_element_t<1, TypeParam>;

		convertible_type conversion = units::unit_cast<convertible_type>(test_type{ 1 });
		test_type result = units::unit_cast<test_type>(conversion);

		EXPECT_EQ(test_type{ 1 }, result);
	}

	// Metric
	using NanometresTuple  = Types<UNITS_TYPE_COMBINE(units::nanometres)>;
	using MicrometresTuple = Types<UNITS_TYPE_COMBINE(units::micrometres)>;
	using MillimetresTuple = Types<UNITS_TYPE_COMBINE(units::millimetres)>;
	using CentimetresTuple = Types<UNITS_TYPE_COMBINE(units::centimetres)>;
	using DecimetresTuple  = Types<UNITS_TYPE_COMBINE(units::decimetres)>;
	using MetresTuple      = Types<UNITS_TYPE_COMBINE(units::metres)>;
	using KilometresTuple  = Types<UNITS_TYPE_COMBINE(units::kilometres)>;

	// Imperial
	using ThousTuple    = Types<UNITS_TYPE_COMBINE(units::thous)>;
	using InchesTuple   = Types<UNITS_TYPE_COMBINE(units::inches)>;
	using LinksTuple    = Types<UNITS_TYPE_COMBINE(units::links)>;
	using FeetTuple     = Types<UNITS_TYPE_COMBINE(units::feet)>;
	using YardsTuple    = Types<UNITS_TYPE_COMBINE(units::yards)>;
	using RodsTuple     = Types<UNITS_TYPE_COMBINE(units::rods)>;
	using ChainsTuple   = Types<UNITS_TYPE_COMBINE(units::chains)>;
	using FurlongsTuple = Types<UNITS_TYPE_COMBINE(units::furlongs)>;
	using MilesTuple    = Types<UNITS_TYPE_COMBINE(units::miles)>;
	using LeaguesTuple  = Types<UNITS_TYPE_COMBINE(units::leagues)>;

	// Maritime
	using FathomsTuple       = Types<UNITS_TYPE_COMBINE(units::fathoms)>;
	using CablesTuple        = Types<UNITS_TYPE_COMBINE(units::cables)>;
	using NauticalMilesTuple = Types<UNITS_TYPE_COMBINE(units::nautical_miles)>;

#undef UNITS_TYPE_COMBINE

	REGISTER_TYPED_TEST_CASE_P(UnitCastTest,
							   UnitCast_WhenConvertedToCompatibleType_WillConvertBackWithoutPrecisionLoss);

	INSTANTIATE_TYPED_TEST_CASE_P(Nanometres, UnitCastTest, NanometresTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Micrometres, UnitCastTest, MicrometresTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Millimetres, UnitCastTest, MillimetresTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Centimetres, UnitCastTest, CentimetresTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(DeciMetres, UnitCastTest, DecimetresTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Metres, UnitCastTest, MetresTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Kilometres, UnitCastTest, KilometresTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Thous, UnitCastTest, ThousTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Inches, UnitCastTest, InchesTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Links, UnitCastTest, LinksTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Feet, UnitCastTest, FeetTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Yards, UnitCastTest, YardsTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Rods, UnitCastTest, RodsTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Chains, UnitCastTest, ChainsTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Furlongs, UnitCastTest, FurlongsTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Miles, UnitCastTest, MilesTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Leagues, UnitCastTest, LeaguesTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Fathoms, UnitCastTest, FathomsTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(Cables, UnitCastTest, CablesTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(NauticalMiles, UnitCastTest, NauticalMilesTuple);

	template <typename T>
	class BritishVsAmericanSpellingTest : public Test
	{
	};

	TYPED_TEST_CASE_P(BritishVsAmericanSpellingTest);

	TYPED_TEST_P(BritishVsAmericanSpellingTest, EitherSpellingYieldsSameType)
	{
		constexpr bool is_same = std::is_same<typename std::tuple_element<0, TypeParam>::type,
		                                      typename std::tuple_element<1, TypeParam>::type>::value;
		EXPECT_TRUE(is_same);
	}

	using BritishVsAmericanSpellingTuple = Types<std::tuple<units::nanometres, units::nanometers>,
	                                             std::tuple<units::micrometres, units::micrometers>,
	                                             std::tuple<units::millimetres, units::millimeters>,
	                                             std::tuple<units::centimetres, units::centimeters>,
	                                             std::tuple<units::decimetres, units::decimeters>,
	                                             std::tuple<units::metres, units::meters>,
	                                             std::tuple<units::kilometres, units::kilometers>>;

	REGISTER_TYPED_TEST_CASE_P(BritishVsAmericanSpellingTest, EitherSpellingYieldsSameType);

	INSTANTIATE_TYPED_TEST_CASE_P(BritishVsAmericanSpelling,
	                              BritishVsAmericanSpellingTest,
	                              BritishVsAmericanSpellingTuple);

	template <typename T>
	class LiteralsTest : public Test
	{
	};

	TYPED_TEST_CASE_P(LiteralsTest);

	TYPED_TEST_P(LiteralsTest, LiteralGeneratesCorrectType)
	{
		using expected_type    = typename std::tuple_element<0, TypeParam>::type;
		using actual_type      = typename std::tuple_element<1, TypeParam>::type;
		constexpr auto is_same = std::is_same<expected_type, actual_type>::value;
		EXPECT_TRUE(is_same) << "Incompatible types";
	}

	using MetricDistanceLiteralsTuple = Types<std::tuple<units::nanometres, decltype(1_nm)>,
	                                          std::tuple<units::micrometres, decltype(1_um)>,
	                                          std::tuple<units::millimetres, decltype(1_mm)>,
	                                          std::tuple<units::centimetres, decltype(1_cm)>,
	                                          std::tuple<units::metres, decltype(1_m)>,
	                                          std::tuple<units::kilometres, decltype(1_km)>>;

	using ImperialDistanceLiteralsTuple = Types<std::tuple<units::inches, decltype(1_in)>,
	                                            std::tuple<units::feet, decltype(1_ft)>,
	                                            std::tuple<units::yards, decltype(1_yd)>,
	                                            std::tuple<units::chains, decltype(1_ch)>,
	                                            std::tuple<units::furlongs, decltype(1_fur)>,
	                                            std::tuple<units::miles, decltype(1_mi)>,
	                                            std::tuple<units::leagues, decltype(1_lea)>,
	                                            std::tuple<units::thous, decltype(1_th)>>;

	using MaritimeDistanceLiteralsTuple = Types<std::tuple<units::fathoms, decltype(1_ftm)>,
	                                            std::tuple<units::cables, decltype(1_cb)>,
	                                            std::tuple<units::nautical_miles, decltype(1_NM)>,
	                                            std::tuple<units::nautical_miles, decltype(1_nmi)>>;

	using AstronomicalUnitsDistanceLiteralsTuple = Types<std::tuple<units::earth_radii, decltype(1_R)>,
	                                                     std::tuple<units::lunar_distances, decltype(1_LD)>,
	                                                     std::tuple<units::astronimical_units, decltype(1_AU)>,
	                                                     std::tuple<units::light_years, decltype(1_ly)>,
	                                                     std::tuple<units::parsecs, decltype(1_pc)>>;

	REGISTER_TYPED_TEST_CASE_P(LiteralsTest, LiteralGeneratesCorrectType);

	INSTANTIATE_TYPED_TEST_CASE_P(MetricDistance, LiteralsTest, MetricDistanceLiteralsTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(ImperialDistance, LiteralsTest, ImperialDistanceLiteralsTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(MaritimeDistance, LiteralsTest, MaritimeDistanceLiteralsTuple);
	INSTANTIATE_TYPED_TEST_CASE_P(AstronomicalUnitsDistance, LiteralsTest, AstronomicalUnitsDistanceLiteralsTuple);
}
<|endoftext|>


<commit_before>#pragma once
namespace std          {
namespace experimental {
namespace parallel     {
inline namespace v1    {

template<int i, int... js>
struct __constexpr_max
{
    static const int value = i < __constexpr_max<js...>::value ? __constexpr_max<js...>::value : i;
};

template<int i>
struct __constexpr_max<i>
{
    static const int value = i;
};

template<class DefaultPolicy, class... Policies>
class __dynamic_execution_policy
{
    private:
        typedef typename std::aligned_storage<
            __constexpr_max<sizeof(DefaultPolicy), sizeof(Policies)...>::value
            >::type policy_storage_type;
        policy_storage_type policy_storage_;
        const type_info *policy_type_;

        template<class ExecutionPolicy>
        bool is_policy() const { return typeid(ExecutionPolicy) == *policy_type_; }

    public:

        template<typename ExecutionPolicy>
        __dynamic_execution_policy(const ExecutionPolicy& exec)
        {
            auto ptr = reinterpret_cast<ExecutionPolicy*>(&policy_storage_);
            new (ptr) ExecutionPolicy(exec);
            policy_type_ = &typeid(ExecutionPolicy);
        }
        /* eg: use default copy/move ctors, dtors, and assignment ops , should be okay*/

        template<class ExecutionPolicy>
        typename enable_if<is_execution_policy<ExecutionPolicy>::value, ExecutionPolicy*>::type
        get()  __NOEXCEPT
        {
            if (!is_policy<ExecutionPolicy>())
            {
                return nullptr;
            }
            return reinterpret_cast<ExecutionPolicy*>(&policy_storage_);
        }
        template<class ExecutionPolicy>
        typename enable_if<is_execution_policy<ExecutionPolicy>::value, const ExecutionPolicy*>::type
        get()  const __NOEXCEPT
        {
            if (!is_policy<ExecutionPolicy>())
            {
                return nullptr;
            }
            return reinterpret_cast<const ExecutionPolicy*>(&policy_storage_);
        }

        const type_info& type() const __NOEXCEPT
        {
            return *policy_type_;
        }

    private:

        // algorithm dispatch : loop over policies to detect the one that needs to be dispatched
        //
        template<class...>
        struct policies_placeholder{};

        template<class... Args>
        decltype(declval<DefaultPolicy>().dispatch(declval<Args>()...))
        dispatch(policies_placeholder<>&&, Args&&... args) const
        {
            return get<DefaultPolicy>()->dispatch(forward<Args>(args)...);
        }

        template<class ExecutionPolicy, class... Execs, class... Args>
        decltype(declval<DefaultPolicy>().dispatch(declval<Args>()...))
        dispatch(policies_placeholder<ExecutionPolicy,Execs...>&&, Args&&... args) const
        {
            if (is_policy<ExecutionPolicy>())
            {
                return get<ExecutionPolicy>()->dispatch(forward<Args>(args)...);
            }
            else
            {
                return dispatch(policies_placeholder<Execs...>{}, forward<Args>(args)...);
            }
        }

    public:

        // algorithm dispatch
        //
        template<class... Args>
        decltype(declval<DefaultPolicy>().dispatch(declval<Args>()...))
        dispatch(Args&&... args) const
        {
            return dispatch(policies_placeholder<DefaultPolicy, Policies...>{}, forward<Args>(args)...);
        }
};

struct execution_policy
{
    private:
        __dynamic_execution_policy<
            sequential_execution_policy,
            parallel_execution_policy
        > policy_;
    public:
        // 2.7.1, execution_policy construct/assign
        template<class ExecutionPolicy>
        execution_policy(const ExecutionPolicy& policy,
                         typename enable_if<is_execution_policy<ExecutionPolicy>::value>::type * = 0) : policy_(policy)
        {}

        template<class ExecutionPolicy>
        typename enable_if<is_execution_policy<ExecutionPolicy>::value,execution_policy&>::type
        operator=(const ExecutionPolicy& policy)
        {
            policy_ = policy;
            return *this;
        }

        // 2.7.2, execution_policy object access
        const type_info& type() const __NOEXCEPT
        {
            return policy_.type();
        }

        template<class ExecutionPolicy>
        ExecutionPolicy* get() __NOEXCEPT
        {
            return policy_.get<ExecutionPolicy>();
        }
        template<class ExecutionPolicy>
        const ExecutionPolicy* get() const __NOEXCEPT
        {
            return policy_.get<ExecutionPolicy>();
        }

        // algorithm dispatch
        //
        template<class... Args>
        auto dispatch(Args&&... args) const  ->
        decltype(policy_.dispatch(forward<Args>(args)...))
        {
            return policy_.dispatch(forward<Args>(args)...);
        }
};

}
}
}
}

<commit_msg>fix typeid comparison<commit_after>#pragma once
namespace std          {
namespace experimental {
namespace parallel     {
inline namespace v1    {

template<int i, int... js>
struct __constexpr_max
{
    static const int value = i < __constexpr_max<js...>::value ? __constexpr_max<js...>::value : i;
};

template<int i>
struct __constexpr_max<i>
{
    static const int value = i;
};

template<class DefaultPolicy, class... Policies>
class __dynamic_execution_policy
{
    private:
        typedef typename std::aligned_storage<
            __constexpr_max<sizeof(DefaultPolicy), sizeof(Policies)...>::value
            >::type policy_storage_type;
        policy_storage_type policy_storage_;
        const type_info *policy_type_;

        template<class ExecutionPolicy>
        bool is_policy() const { return typeid(ExecutionPolicy).hash_code() == policy_type_->hash_code(); }

    public:

        template<typename ExecutionPolicy>
        __dynamic_execution_policy(const ExecutionPolicy& exec)
        {
            auto ptr = reinterpret_cast<ExecutionPolicy*>(&policy_storage_);
            new (ptr) ExecutionPolicy(exec);
            policy_type_ = &typeid(ExecutionPolicy);
        }
        /* eg: use default copy/move ctors, dtors, and assignment ops , should be okay*/

        template<class ExecutionPolicy>
        typename enable_if<is_execution_policy<ExecutionPolicy>::value, ExecutionPolicy*>::type
        get()  __NOEXCEPT
        {
            if (!is_policy<ExecutionPolicy>())
            {
                return nullptr;
            }
            return reinterpret_cast<ExecutionPolicy*>(&policy_storage_);
        }
        template<class ExecutionPolicy>
        typename enable_if<is_execution_policy<ExecutionPolicy>::value, const ExecutionPolicy*>::type
        get()  const __NOEXCEPT
        {
            if (!is_policy<ExecutionPolicy>())
            {
                return nullptr;
            }
            return reinterpret_cast<const ExecutionPolicy*>(&policy_storage_);
        }

        const type_info& type() const __NOEXCEPT
        {
            return *policy_type_;
        }

    private:

        // algorithm dispatch : loop over policies to detect the one that needs to be dispatched
        //
        template<class...>
        struct policies_placeholder{};

        template<class... Args>
        decltype(declval<DefaultPolicy>().dispatch(declval<Args>()...))
        dispatch(policies_placeholder<>&&, Args&&... args) const
        {
            return get<DefaultPolicy>()->dispatch(forward<Args>(args)...);
        }

        template<class ExecutionPolicy, class... Execs, class... Args>
        decltype(declval<DefaultPolicy>().dispatch(declval<Args>()...))
        dispatch(policies_placeholder<ExecutionPolicy,Execs...>&&, Args&&... args) const
        {
            if (is_policy<ExecutionPolicy>())
            {
                return get<ExecutionPolicy>()->dispatch(forward<Args>(args)...);
            }
            else
            {
                return dispatch(policies_placeholder<Execs...>{}, forward<Args>(args)...);
            }
        }

    public:

        // algorithm dispatch
        //
        template<class... Args>
        decltype(declval<DefaultPolicy>().dispatch(declval<Args>()...))
        dispatch(Args&&... args) const
        {
            return dispatch(policies_placeholder<DefaultPolicy, Policies...>{}, forward<Args>(args)...);
        }
};

struct execution_policy
{
    private:
        __dynamic_execution_policy<
            sequential_execution_policy,
            parallel_execution_policy
        > policy_;
    public:
        // 2.7.1, execution_policy construct/assign
        template<class ExecutionPolicy>
        execution_policy(const ExecutionPolicy& policy,
                         typename enable_if<is_execution_policy<ExecutionPolicy>::value>::type * = 0) : policy_(policy)
        {}

        template<class ExecutionPolicy>
        typename enable_if<is_execution_policy<ExecutionPolicy>::value,execution_policy&>::type
        operator=(const ExecutionPolicy& policy)
        {
            policy_ = policy;
            return *this;
        }

        // 2.7.2, execution_policy object access
        const type_info& type() const __NOEXCEPT
        {
            return policy_.type();
        }

        template<class ExecutionPolicy>
        ExecutionPolicy* get() __NOEXCEPT
        {
            return policy_.get<ExecutionPolicy>();
        }
        template<class ExecutionPolicy>
        const ExecutionPolicy* get() const __NOEXCEPT
        {
            return policy_.get<ExecutionPolicy>();
        }

        // algorithm dispatch
        //
        template<class... Args>
        auto dispatch(Args&&... args) const  ->
        decltype(policy_.dispatch(forward<Args>(args)...))
        {
            return policy_.dispatch(forward<Args>(args)...);
        }
};

}
}
}
}

<|endoftext|>


<commit_before>/*
Copyright (c) 2012-2014 The SSDB Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
*/
// todo r2m adaptation : remove this
#include "t_kv.h"
#include "codec/encode.h"
#include "codec/decode.h"

int SSDBImpl::SetGeneric(const std::string &key, const std::string &val, int flags, const int64_t expire, char log_type){
	if (expire < 0){
		return -1;
	}

	std::string key_type;
	if (type(key, &key_type) == -1){
		return -1;
	}

	if ((flags & OBJ_SET_NX) && (key_type != "none")){
		return -1;
	} else if ((flags & OBJ_SET_XX) && (key_type == "none")){
		return -1;
	}

	Transaction trans(binlogs);

	if (key_type != "none"){
		DelKeyByType(key, key_type);
	}

	if (expire > 0){
        expiration->set_ttl_internal(key, expire);
	}

	std::string meta_key = encode_meta_key(key);
	std::string meta_val = encode_kv_val(val);
	binlogs->Put(meta_key, meta_val);
	binlogs->add_log(log_type, BinlogCommand::KSET, meta_key);
	leveldb::Status s = binlogs->commit();
	if (!s.ok()){
        //todo 时间戳排序回滚fast_keys first_timeout
		return -1;
	}
    return 0;
}

int SSDBImpl::multi_set(const std::vector<Bytes> &kvs, int offset, char log_type){
	Transaction trans(binlogs);

	std::vector<Bytes>::const_iterator it;
	it = kvs.begin() + offset;
	for(; it != kvs.end(); it += 2){
		const Bytes &key = *it;
        std::string key_type;
        int ret = type(key, &key_type);
        if (ret == -1){
            return  -1;
        } else if (ret == 1){
            DelKeyByType(key, key_type);
        }

		const Bytes &val = *(it + 1);
		std::string buf = encode_meta_key(key.String());
        std::string meta_val = encode_kv_val(val.String());
		binlogs->Put(buf, meta_val);
		binlogs->add_log(log_type, BinlogCommand::KSET, buf);
	}
	leveldb::Status s = binlogs->commit();
	if(!s.ok()){
		log_error("multi_set error: %s", s.ToString().c_str());
		return -1;
	}
	return (kvs.size() - offset)/2;
}

int SSDBImpl::multi_del(const std::vector<Bytes> &keys, int offset, char log_type){ //注：redis中不支持该接口
	Transaction trans(binlogs);

	std::vector<Bytes>::const_iterator it;
	it = keys.begin() + offset;
	for(; it != keys.end(); it++){
		const Bytes &key = *it;
// todo r2m adaptation
        std::string key_type;
        int ret = type(key, &key_type);
        if (ret == -1){
            return -1;
        } else if(ret == 1){
            DelKeyByType(key, key_type);
        }
	}
	leveldb::Status s = binlogs->commit();
	if(!s.ok()){
		log_error("multi_del error: %s", s.ToString().c_str());
		return -1;
	}
	return keys.size() - offset;
}

int SSDBImpl::set(const Bytes &key, const Bytes &val, char log_type){
    return SetGeneric(key.String(), val.String(), OBJ_SET_NO_FLAGS, 0);
}

int SSDBImpl::setnx(const Bytes &key, const Bytes &val, char log_type){
    return SetGeneric(key.String(), val.String(), OBJ_SET_NX, 0);
}

int SSDBImpl::getset(const Bytes &key, std::string *val, const Bytes &newval, char log_type){
    std::string key_type;
    int ret = type(key, &key_type);
    if (ret == -1){
        return -1;
    } else if (ret == 1 && key_type != "string"){
        return -1;
    } else if (ret == 1 && key_type == "string"){
        get(key, val);
    }

	Transaction trans(binlogs);

	std::string buf = encode_meta_key(key.String());
    std::string meta_val = encode_kv_val(newval.String());
	binlogs->Put(buf, meta_val);
	binlogs->add_log(log_type, BinlogCommand::KSET, buf);
	leveldb::Status s = binlogs->commit();
	if(!s.ok()){
		log_error("set error: %s", s.ToString().c_str());
		return -1;
	}
	return ret;
}

int SSDBImpl::del(const Bytes &key, char log_type){
    std::string key_type;
    int ret = type(key, &key_type);
    if (ret == -1){
        return -1;
    }
    if (key_type == "string"){
        KDel(key);
    } else if (key_type == "hash"){
        hclear(key);
    } else if (key_type == "set"){
        //todo
    } else if (key_type == "zset"){
        //todo
    } else if (key_type == "list"){
        //todo
    }

/*	Transaction trans(binlogs);

// todo r2m adaptation
	std::string buf = encode_kv_key(key);
	binlogs->Delete(buf);
	binlogs->add_log(log_type, BinlogCommand::KDEL, buf);
	leveldb::Status s = binlogs->commit();
	if(!s.ok()){
		log_error("del error: %s", s.ToString().c_str());
		return -1;
	}*/
	return 1;
}

int SSDBImpl::incr(const Bytes &key, int64_t by, int64_t *new_val, char log_type){
	Transaction trans(binlogs);

	std::string old;
	int ret = this->get(key, &old);
	if(ret == -1){
		return -1;
	}else if(ret == 0){
		*new_val = by;
	}else{
        int64_t oldvalue = str_to_int64(old);
        if(errno != 0){
            return 0;
        }
        if ((by < 0 && oldvalue < 0 && by < (LLONG_MIN-oldvalue)) ||
            (by > 0 && oldvalue > 0 && by > (LLONG_MAX-oldvalue))) {
            return 0;
        }
		*new_val = oldvalue + by;
	}

	std::string buf = encode_meta_key(key.String());
    std::string meta_val = encode_kv_val(str(*new_val));
	binlogs->Put(buf, meta_val);
	binlogs->add_log(log_type, BinlogCommand::KSET, buf);

	leveldb::Status s = binlogs->commit();
	if(!s.ok()){
		log_error("del error: %s", s.ToString().c_str());
		return -1;
	}
	return 1;
}

int SSDBImpl::get(const Bytes &key, std::string *val){
	std::string buf = encode_meta_key(key.String());
    std::string en_val;

	leveldb::Status s = ldb->Get(leveldb::ReadOptions(), buf, &en_val);
	if(s.IsNotFound()){
		return 0;
	}
	if(!s.ok()){
		log_error("get error: %s", s.ToString().c_str());
		return -1;
	}
    KvMetaVal kv;
    if (kv.DecodeMetaVal(en_val) == -1){
        return -1;
    } else{
        *val = kv.value;
    }
	return 1;
}

// todo r2m adaptation
KIterator* SSDBImpl::scan(const Bytes &start, const Bytes &end, uint64_t limit){
	std::string key_start, key_end;
	key_start = encode_kv_key(start);
	if(end.empty()){
		key_end = "";
	}else{
		key_end = encode_kv_key(end);
	}
	//dump(key_start.data(), key_start.size(), "scan.start");
	//dump(key_end.data(), key_end.size(), "scan.end");

	return new KIterator(this->iterator(key_start, key_end, limit));
}

// todo r2m adaptation
KIterator* SSDBImpl::rscan(const Bytes &start, const Bytes &end, uint64_t limit){
	std::string key_start, key_end;

	key_start = encode_kv_key(start);
	if(start.empty()){
		key_start.append(1, 255);
	}
	if(!end.empty()){
		key_end = encode_kv_key(end);
	}
	//dump(key_start.data(), key_start.size(), "scan.start");
	//dump(key_end.data(), key_end.size(), "scan.end");

	return new KIterator(this->rev_iterator(key_start, key_end, limit));
}

int SSDBImpl::setbit(const Bytes &key, int bitoffset, int on, char log_type){
	if(key.empty()){
		log_error("empty key!");
		return 0;
	}
	Transaction trans(binlogs);

	std::string val;
	int ret = this->get(key, &val);
	if(ret == -1){
		return -1;
	}

	int len = bitoffset / 8;
	int bit = bitoffset % 8;
	if(len >= val.size()){
		val.resize(len + 1, 0);
	}
	int orig = val[len] & (1 << bit);
	if(on == 1){
		val[len] |= (1 << bit);
	}else{
		val[len] &= ~(1 << bit);
	}

// todo r2m adaptation
	std::string buf = encode_kv_key(key);
	binlogs->Put(buf, val);
	binlogs->add_log(log_type, BinlogCommand::KSET, buf);
	leveldb::Status s = binlogs->commit();
	if(!s.ok()){
		log_error("set error: %s", s.ToString().c_str());
		return -1;
	}
	return orig;
}

int SSDBImpl::getbit(const Bytes &key, int bitoffset){
	std::string val;
	int ret = this->get(key, &val);
	if(ret == -1){
		return -1;
	}

	int len = bitoffset / 8;
	int bit = bitoffset % 8;
	if(len >= val.size()){
		return 0;
	}
	return (val[len] & (1 << bit)) == 0? 0 : 1;
}

/*
 * private API
 */
int SSDBImpl::DelKeyByType(const Bytes &key, const std::string &type){
	//todo 内部接口，保证操作的原子性，调用No Commit接口
	int ret = 0;
	if ("string" == type){
		ret = KDelNoLock(key);
	} else if ("hash" == type){
//		s = HDelKeyNoLock(key, &res);
	} else if ("list" == type){
//		s = LDelKeyNoLock(key, &res);
	} else if ("set" == type){
//		s = SDelKeyNoLock(key, &res);
	} else if ("zset" == type){
//		s = ZDelKeyNoLock(key, &res);
	}

	return 0;
}

int SSDBImpl::KDel(const Bytes &key, char log_type){
    Transaction trans(binlogs);

    std::string buf = encode_meta_key(key.String());
    binlogs->Delete(buf);
    binlogs->add_log(log_type, BinlogCommand::KDEL, buf);

    leveldb::Status s = binlogs->commit();
    if(!s.ok()){
        log_error("set error: %s", s.ToString().c_str());
        return -1;
    }
    return 1;
}

int SSDBImpl::KDelNoLock(const Bytes &key, char log_type){
	std::string buf = encode_meta_key(key.String());
	binlogs->Delete(buf);
	binlogs->add_log(log_type, BinlogCommand::KDEL, buf);
	return 0;
}

/*
 * General API
 */
int SSDBImpl::type(const Bytes &key, std::string *type){
	*type = "none";
    int ret = 0;
	std::string val;
	std::string meta_key = encode_meta_key(key.String());
	leveldb::Status s = ldb->Get(leveldb::ReadOptions(), meta_key, &val);
	if(s.IsNotFound()){
		return 0;
	}
	if(!s.ok()){
		log_error("get error: %s", s.ToString().c_str());
		return -1;
	}

	if (val[0] == DataType::KV){
		*type = "string";
        ret = 1;
	} else if (val[0] == DataType::HSIZE){
		HashMetaVal hv;
		if (hv.DecodeMetaVal(val) == -1){
			return -1;
		}
		if (hv.del == KEY_ENABLED_MASK){
			*type = "hash";
            ret = 1;
		}
	} else if (val[0] == DataType::SSIZE){
		SetMetaVal sv;
		if (sv.DecodeMetaVal(val) == -1){
			return -1;
		}
		if (sv.del == KEY_ENABLED_MASK){
			*type = "set";
            ret = 1;
		}
	} else if (val[0] == DataType::ZSIZE){
		ZSetMetaVal zs;
		if (zs.DecodeMetaVal(val) == -1){
			return -1;
		}
		if (zs.del == KEY_ENABLED_MASK){
			*type = "zset";
            ret = 1;
		}
	} else if (val[0] == DataType::LSZIE){
		ListMetaVal ls;
		if (ls.DecodeMetaVal(val) == -1){
			return -1;
		}
		if (ls.del == KEY_ENABLED_MASK){
			*type = "list";
            ret = 1;
		}
	} else{
		return -1;
	}

	return ret;
}
<commit_msg>实现kv setbit/getbit API<commit_after>/*
Copyright (c) 2012-2014 The SSDB Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
*/
// todo r2m adaptation : remove this
#include "t_kv.h"
#include "codec/encode.h"
#include "codec/decode.h"

int SSDBImpl::SetGeneric(const std::string &key, const std::string &val, int flags, const int64_t expire, char log_type){
	if (expire < 0){
		return -1;
	}

	std::string key_type;
	if (type(key, &key_type) == -1){
		return -1;
	}

	if ((flags & OBJ_SET_NX) && (key_type != "none")){
		return -1;
	} else if ((flags & OBJ_SET_XX) && (key_type == "none")){
		return -1;
	}

	Transaction trans(binlogs);

	if (key_type != "none"){
		DelKeyByType(key, key_type);
	}

	if (expire > 0){
        expiration->set_ttl_internal(key, expire);
	}

	std::string meta_key = encode_meta_key(key);
	std::string meta_val = encode_kv_val(val);
	binlogs->Put(meta_key, meta_val);
	binlogs->add_log(log_type, BinlogCommand::KSET, meta_key);
	leveldb::Status s = binlogs->commit();
	if (!s.ok()){
        //todo 时间戳排序回滚fast_keys first_timeout
		return -1;
	}
    return 0;
}

int SSDBImpl::multi_set(const std::vector<Bytes> &kvs, int offset, char log_type){
	Transaction trans(binlogs);

	std::vector<Bytes>::const_iterator it;
	it = kvs.begin() + offset;
	for(; it != kvs.end(); it += 2){
		const Bytes &key = *it;
        std::string key_type;
        int ret = type(key, &key_type);
        if (ret == -1){
            return  -1;
        } else if (ret == 1){
            DelKeyByType(key, key_type);
        }

		const Bytes &val = *(it + 1);
		std::string buf = encode_meta_key(key.String());
        std::string meta_val = encode_kv_val(val.String());
		binlogs->Put(buf, meta_val);
		binlogs->add_log(log_type, BinlogCommand::KSET, buf);
	}
	leveldb::Status s = binlogs->commit();
	if(!s.ok()){
		log_error("multi_set error: %s", s.ToString().c_str());
		return -1;
	}
	return (kvs.size() - offset)/2;
}

int SSDBImpl::multi_del(const std::vector<Bytes> &keys, int offset, char log_type){ //注：redis中不支持该接口
	Transaction trans(binlogs);

	std::vector<Bytes>::const_iterator it;
	it = keys.begin() + offset;
	for(; it != keys.end(); it++){
		const Bytes &key = *it;
// todo r2m adaptation
        std::string key_type;
        int ret = type(key, &key_type);
        if (ret == -1){
            return -1;
        } else if(ret == 1){
            DelKeyByType(key, key_type);
        }
	}
	leveldb::Status s = binlogs->commit();
	if(!s.ok()){
		log_error("multi_del error: %s", s.ToString().c_str());
		return -1;
	}
	return keys.size() - offset;
}

int SSDBImpl::set(const Bytes &key, const Bytes &val, char log_type){
    return SetGeneric(key.String(), val.String(), OBJ_SET_NO_FLAGS, 0);
}

int SSDBImpl::setnx(const Bytes &key, const Bytes &val, char log_type){
    return SetGeneric(key.String(), val.String(), OBJ_SET_NX, 0);
}

int SSDBImpl::getset(const Bytes &key, std::string *val, const Bytes &newval, char log_type){
    std::string key_type;
    int ret = type(key, &key_type);
    if (ret == -1){
        return -1;
    } else if (ret == 1 && key_type != "string"){
        return -1;
    } else if (ret == 1 && key_type == "string"){
        get(key, val);
    }

	Transaction trans(binlogs);

	std::string buf = encode_meta_key(key.String());
    std::string meta_val = encode_kv_val(newval.String());
	binlogs->Put(buf, meta_val);
	binlogs->add_log(log_type, BinlogCommand::KSET, buf);
	leveldb::Status s = binlogs->commit();
	if(!s.ok()){
		log_error("set error: %s", s.ToString().c_str());
		return -1;
	}
	return ret;
}

int SSDBImpl::del(const Bytes &key, char log_type){
    std::string key_type;
    int ret = type(key, &key_type);
    if (ret == -1){
        return -1;
    }
    if (key_type == "string"){
        KDel(key);
    } else if (key_type == "hash"){
        hclear(key);
    } else if (key_type == "set"){
        //todo
    } else if (key_type == "zset"){
        //todo
    } else if (key_type == "list"){
        //todo
    }

/*	Transaction trans(binlogs);

// todo r2m adaptation
	std::string buf = encode_kv_key(key);
	binlogs->Delete(buf);
	binlogs->add_log(log_type, BinlogCommand::KDEL, buf);
	leveldb::Status s = binlogs->commit();
	if(!s.ok()){
		log_error("del error: %s", s.ToString().c_str());
		return -1;
	}*/
	return 1;
}

int SSDBImpl::incr(const Bytes &key, int64_t by, int64_t *new_val, char log_type){
	Transaction trans(binlogs);

	std::string old;
	int ret = this->get(key, &old);
	if(ret == -1){
		return -1;
	}else if(ret == 0){
		*new_val = by;
	}else{
        int64_t oldvalue = str_to_int64(old);
        if(errno != 0){
            return 0;
        }
        if ((by < 0 && oldvalue < 0 && by < (LLONG_MIN-oldvalue)) ||
            (by > 0 && oldvalue > 0 && by > (LLONG_MAX-oldvalue))) {
            return 0;
        }
		*new_val = oldvalue + by;
	}

	std::string buf = encode_meta_key(key.String());
    std::string meta_val = encode_kv_val(str(*new_val));
	binlogs->Put(buf, meta_val);
	binlogs->add_log(log_type, BinlogCommand::KSET, buf);

	leveldb::Status s = binlogs->commit();
	if(!s.ok()){
		log_error("del error: %s", s.ToString().c_str());
		return -1;
	}
	return 1;
}

int SSDBImpl::get(const Bytes &key, std::string *val){
	std::string buf = encode_meta_key(key.String());
    std::string en_val;

	leveldb::Status s = ldb->Get(leveldb::ReadOptions(), buf, &en_val);
	if(s.IsNotFound()){
		return 0;
	}
	if(!s.ok()){
		log_error("get error: %s", s.ToString().c_str());
		return -1;
	}
    KvMetaVal kv;
    if (kv.DecodeMetaVal(en_val) == -1){
        return -1;
    } else{
        *val = kv.value;
    }
	return 1;
}

// todo r2m adaptation
KIterator* SSDBImpl::scan(const Bytes &start, const Bytes &end, uint64_t limit){
	std::string key_start, key_end;
	key_start = encode_kv_key(start);
	if(end.empty()){
		key_end = "";
	}else{
		key_end = encode_kv_key(end);
	}
	//dump(key_start.data(), key_start.size(), "scan.start");
	//dump(key_end.data(), key_end.size(), "scan.end");

	return new KIterator(this->iterator(key_start, key_end, limit));
}

// todo r2m adaptation
KIterator* SSDBImpl::rscan(const Bytes &start, const Bytes &end, uint64_t limit){
	std::string key_start, key_end;

	key_start = encode_kv_key(start);
	if(start.empty()){
		key_start.append(1, 255);
	}
	if(!end.empty()){
		key_end = encode_kv_key(end);
	}
	//dump(key_start.data(), key_start.size(), "scan.start");
	//dump(key_end.data(), key_end.size(), "scan.end");

	return new KIterator(this->rev_iterator(key_start, key_end, limit));
}

int SSDBImpl::setbit(const Bytes &key, int bitoffset, int on, char log_type){
	if(key.empty()){
		log_error("empty key!");
		return 0;
	}
	Transaction trans(binlogs);

	std::string val;
	int ret = this->get(key, &val);
	if(ret == -1){
		return -1;
	}

    int len = bitoffset >> 3;
    int bit = 7 - (bitoffset & 0x7);
	if(len >= val.size()){
		val.resize(len + 1, 0);
	}
	int orig = val[len] & (1 << bit);
	if(on == 1){
		val[len] |= (1 << bit);
	}else{
		val[len] &= ~(1 << bit);
	}

	std::string buf = encode_meta_key(key.String());
    std::string meta_val = encode_kv_val(val);
	binlogs->Put(buf, meta_val);
	binlogs->add_log(log_type, BinlogCommand::KSET, buf);
	leveldb::Status s = binlogs->commit();
	if(!s.ok()){
		log_error("set error: %s", s.ToString().c_str());
		return -1;
	}
	return orig;
}

int SSDBImpl::getbit(const Bytes &key, int bitoffset){
	std::string val;
	int ret = this->get(key, &val);
	if(ret == -1){
		return -1;
	}

    int len = bitoffset >> 3;
    int bit = 7 - (bitoffset & 0x7);
	if(len >= val.size()){
		return 0;
	}
	return (val[len] & (1 << bit)) == 0? 0 : 1;
}

/*
 * private API
 */
int SSDBImpl::DelKeyByType(const Bytes &key, const std::string &type){
	//todo 内部接口，保证操作的原子性，调用No Commit接口
	int ret = 0;
	if ("string" == type){
		ret = KDelNoLock(key);
	} else if ("hash" == type){
//		s = HDelKeyNoLock(key, &res);
	} else if ("list" == type){
//		s = LDelKeyNoLock(key, &res);
	} else if ("set" == type){
//		s = SDelKeyNoLock(key, &res);
	} else if ("zset" == type){
//		s = ZDelKeyNoLock(key, &res);
	}

	return 0;
}

int SSDBImpl::KDel(const Bytes &key, char log_type){
    Transaction trans(binlogs);

    std::string buf = encode_meta_key(key.String());
    binlogs->Delete(buf);
    binlogs->add_log(log_type, BinlogCommand::KDEL, buf);

    leveldb::Status s = binlogs->commit();
    if(!s.ok()){
        log_error("set error: %s", s.ToString().c_str());
        return -1;
    }
    return 1;
}

int SSDBImpl::KDelNoLock(const Bytes &key, char log_type){
	std::string buf = encode_meta_key(key.String());
	binlogs->Delete(buf);
	binlogs->add_log(log_type, BinlogCommand::KDEL, buf);
	return 0;
}

/*
 * General API
 */
int SSDBImpl::type(const Bytes &key, std::string *type){
	*type = "none";
    int ret = 0;
	std::string val;
	std::string meta_key = encode_meta_key(key.String());
	leveldb::Status s = ldb->Get(leveldb::ReadOptions(), meta_key, &val);
	if(s.IsNotFound()){
		return 0;
	}
	if(!s.ok()){
		log_error("get error: %s", s.ToString().c_str());
		return -1;
	}

	if (val[0] == DataType::KV){
		*type = "string";
        ret = 1;
	} else if (val[0] == DataType::HSIZE){
		HashMetaVal hv;
		if (hv.DecodeMetaVal(val) == -1){
			return -1;
		}
		if (hv.del == KEY_ENABLED_MASK){
			*type = "hash";
            ret = 1;
		}
	} else if (val[0] == DataType::SSIZE){
		SetMetaVal sv;
		if (sv.DecodeMetaVal(val) == -1){
			return -1;
		}
		if (sv.del == KEY_ENABLED_MASK){
			*type = "set";
            ret = 1;
		}
	} else if (val[0] == DataType::ZSIZE){
		ZSetMetaVal zs;
		if (zs.DecodeMetaVal(val) == -1){
			return -1;
		}
		if (zs.del == KEY_ENABLED_MASK){
			*type = "zset";
            ret = 1;
		}
	} else if (val[0] == DataType::LSZIE){
		ListMetaVal ls;
		if (ls.DecodeMetaVal(val) == -1){
			return -1;
		}
		if (ls.del == KEY_ENABLED_MASK){
			*type = "list";
            ret = 1;
		}
	} else{
		return -1;
	}

	return ret;
}
<|endoftext|>


<commit_before>#include "maths.hpp"

namespace stats
{
	// normal distribution

	template <typename float_t> class norm
	{
		float_t mu, sigma, unit;

	 public:

	 	norm(float_t mu=0, float_t sigma=1)
	 	{
	 	 	unit = maths::sqrt2pi*sigma;
	 	 	this->sigma = sigma;
	 		this->mu = mu;
	 	}

	 	float_t pdf(float_t x)
	 	{
	 		float_t z = (x - mu)/sigma;
	 		return maths::exp(-z*z/2)/unit;
	 	}

	 	float_t cdf(float_t x)
	 	{
	 		float_t z = (x - mu)/sigma;
	 		return (1 + maths::erf(z/maths::sqrt2))/2/sigma;
	 	}
	};

	template <typename float_t> float_t dnorm(float_t x, float_t mu=0, float_t sigma=1)
	{
		return norm<float_t>(mu, sigma).pdf(x);
	}

	template <typename float_t> float_t pnorm(float_t x, float_t mu=0, float_t sigma=1)
	{
		return norm<float_t>(mu, sigma).cdf(x);
	}

}; // namespace stats

<commit_msg>Added gamma distribution pdf and cdf<commit_after>#include "maths.hpp"

namespace stats
{
	// normal distribution

	template <typename float_t>
	float_t dnorm(float_t x, float_t mu=0, float_t sigma=1)
	{
		float_t z = (x -  mu)/sigma;
		return maths::exp(-z*z/2)/maths::sqrt2pi/sigma;
	}

	template <typename float_t>
	float_t pnorm(float_t x, float_t mu=0, float_t sigma=1)
	{
		float_t z = (x - mu)/sigma;
		return (1 + maths::erf(z/maths::sqrt2))/2/sigma;
	}

	// gamma distribution

	template <typename float_t>
	float_t dgamma(float_t x, float_t a, float_t b)
	{
		return maths::pow(x*b, a)*maths::exp(-x*b)/maths::tgamma(a)/x;
	}

	template <typename float_t>
	float_t pgamma(float_t x, float_t a, float_t b)
	{
		return maths::igamma(a, x*b)/maths::tgamma(a);
	}

}; // namespace stats

<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_FUN_ATANH_HPP
#define STAN_MATH_PRIM_FUN_ATANH_HPP

#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/err.hpp>
#include <stan/math/prim/fun/is_nan.hpp>
#include <cmath>

namespace stan {
namespace math {

/**
 * Return the inverse hyperbolic tangent of the specified value.
 * An argument of -1 returns negative infinity and an argument of 1
 * returns infinity.
 * Returns nan for nan argument.
 *
 * @param[in] x Argument.
 * @return Inverse hyperbolic tangent of the argument.
 * @throw std::domain_error If argument is not in [-1, 1].
 */
inline double atanh(double x) {
  if (is_nan(x)) {
    return x;
  } else {
    check_bounded("atanh", "x", x, -1.0, 1.0);
    return std::atanh(x);
  }
}

/**
 * Integer version of atanh.
 *
 * @param[in] x Argument.
 * @return Inverse hyperbolic tangent of the argument.
 * @throw std::domain_error If argument is less than 1.
 */
inline double atanh(int x) {
  if (is_nan(x)) {
    return x;
  } else {
    check_bounded("atanh", "x", x, -1, 1);
    return std::atanh(x);
  }
}

/**
 * Structure to wrap atanh() so it can be vectorized.
 */
struct atanh_fun {
  /**
   * Return the inverse hyperbolic tangent of the specified argument.
   *
   * @tparam T type of argument
   * @param x argument
   * @return Inverse hyperbolic tangent of the argument.
   */
  template <typename T>
  static inline T fun(const T& x) {
    return atanh(x);
  }
};

/**
 * Return the elementwise application of atanh() to
 * specified argument container.  The return type promotes the
 * underlying scalar argument type to double if it is an integer,
 * and otherwise is the argument type.
 *
 * @tparam T type of container
 * @param x container
 * @return Elementwise atanh of members of container.
 */
template <typename T>
inline auto atanh(const T& x) {
  return apply_scalar_unary<atanh_fun, T>::apply(x);
}

}  // namespace math
}  // namespace stan

#endif
<commit_msg>remove nan check for atanh(int)<commit_after>#ifndef STAN_MATH_PRIM_FUN_ATANH_HPP
#define STAN_MATH_PRIM_FUN_ATANH_HPP

#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/err.hpp>
#include <stan/math/prim/fun/is_nan.hpp>
#include <cmath>

namespace stan {
namespace math {

/**
 * Return the inverse hyperbolic tangent of the specified value.
 * An argument of -1 returns negative infinity and an argument of 1
 * returns infinity.
 * Returns nan for nan argument.
 *
 * @param[in] x Argument.
 * @return Inverse hyperbolic tangent of the argument.
 * @throw std::domain_error If argument is not in [-1, 1].
 */
inline double atanh(double x) {
  if (is_nan(x)) {
    return x;
  } else {
    check_bounded("atanh", "x", x, -1.0, 1.0);
    return std::atanh(x);
  }
}

/**
 * Integer version of atanh.
 *
 * @param[in] x Argument.
 * @return Inverse hyperbolic tangent of the argument.
 * @throw std::domain_error If argument is less than 1.
 */
inline double atanh(int x) {
  check_bounded("atanh", "x", x, -1, 1);
  return std::atanh(x);
}

/**
 * Structure to wrap atanh() so it can be vectorized.
 */
struct atanh_fun {
  /**
   * Return the inverse hyperbolic tangent of the specified argument.
   *
   * @tparam T type of argument
   * @param x argument
   * @return Inverse hyperbolic tangent of the argument.
   */
  template <typename T>
  static inline T fun(const T& x) {
    return atanh(x);
  }
};

/**
 * Return the elementwise application of atanh() to
 * specified argument container.  The return type promotes the
 * underlying scalar argument type to double if it is an integer,
 * and otherwise is the argument type.
 *
 * @tparam T type of container
 * @param x container
 * @return Elementwise atanh of members of container.
 */
template <typename T>
inline auto atanh(const T& x) {
  return apply_scalar_unary<atanh_fun, T>::apply(x);
}

}  // namespace math
}  // namespace stan

#endif
<|endoftext|>


<commit_before><commit_msg>Some more fixes<commit_after><|endoftext|>


<commit_before>#include "common/network/listen_socket_impl.h"

#include <sys/socket.h>
#include <sys/types.h>

#include <string>

#include "envoy/common/exception.h"

#include "common/common/assert.h"
#include "common/common/fmt.h"
#include "common/network/address_impl.h"
#include "common/network/utility.h"

namespace Envoy {
namespace Network {

void ListenSocketImpl::doBind() {
  const Api::SysCallIntResult result = local_address_->bind(fd_);
  if (result.rc_ == -1) {
    close();
    throw EnvoyException(
        fmt::format("cannot bind '{}': {}", local_address_->asString(), strerror(result.errno_)));
  }
  if (local_address_->type() == Address::Type::Ip && local_address_->ip()->port() == 0) {
    // If the port we bind is zero, then the OS will pick a free port for us (assuming there are
    // any), and we need to find out the port number that the OS picked.
    local_address_ = Address::addressFromFd(fd_);
  }
}

void ListenSocketImpl::setListenSocketOptions(const Network::Socket::OptionsSharedPtr& options) {
  if (!Network::Socket::applyOptions(options, *this,
                                     envoy::api::v2::core::SocketOption::STATE_PREBIND)) {
    throw EnvoyException("ListenSocket: Setting socket options failed");
  }
}

void ListenSocketImpl::setupSocket(const Network::Socket::OptionsSharedPtr& options,
                                   bool bind_to_port) {
  setListenSocketOptions(options);

  if (bind_to_port) {
    doBind();
  }
}

template <>
void NetworkListenSocket<
    NetworkSocketTrait<Address::SocketType::Stream>>::setPrebindSocketOptions() {
  // TODO(htuch): This might benefit from moving to SocketOptionImpl.
  int on = 1;
  int rc = setsockopt(fd_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
  RELEASE_ASSERT(rc != -1, "");
}

template <>
void NetworkListenSocket<
    NetworkSocketTrait<Address::SocketType::Datagram>>::setPrebindSocketOptions() {}

UdsListenSocket::UdsListenSocket(const Address::InstanceConstSharedPtr& address)
    : ListenSocketImpl(address->socket(Address::SocketType::Stream), address) {
  RELEASE_ASSERT(fd_ != -1, "");
  doBind();
}

UdsListenSocket::UdsListenSocket(int fd, const Address::InstanceConstSharedPtr& address)
    : ListenSocketImpl(fd, address) {}

} // namespace Network
} // namespace Envoy
<commit_msg>Use os_sys_calls_impl for setting TCP socket options (#5149)<commit_after>#include "common/network/listen_socket_impl.h"

#include <sys/socket.h>
#include <sys/types.h>

#include <string>

#include "envoy/common/exception.h"

#include "common/api/os_sys_calls_impl.h"
#include "common/common/assert.h"
#include "common/common/fmt.h"
#include "common/network/address_impl.h"
#include "common/network/utility.h"

namespace Envoy {
namespace Network {

void ListenSocketImpl::doBind() {
  const Api::SysCallIntResult result = local_address_->bind(fd_);
  if (result.rc_ == -1) {
    close();
    throw EnvoyException(
        fmt::format("cannot bind '{}': {}", local_address_->asString(), strerror(result.errno_)));
  }
  if (local_address_->type() == Address::Type::Ip && local_address_->ip()->port() == 0) {
    // If the port we bind is zero, then the OS will pick a free port for us (assuming there are
    // any), and we need to find out the port number that the OS picked.
    local_address_ = Address::addressFromFd(fd_);
  }
}

void ListenSocketImpl::setListenSocketOptions(const Network::Socket::OptionsSharedPtr& options) {
  if (!Network::Socket::applyOptions(options, *this,
                                     envoy::api::v2::core::SocketOption::STATE_PREBIND)) {
    throw EnvoyException("ListenSocket: Setting socket options failed");
  }
}

void ListenSocketImpl::setupSocket(const Network::Socket::OptionsSharedPtr& options,
                                   bool bind_to_port) {
  setListenSocketOptions(options);

  if (bind_to_port) {
    doBind();
  }
}

template <>
void NetworkListenSocket<
    NetworkSocketTrait<Address::SocketType::Stream>>::setPrebindSocketOptions() {

  int on = 1;
  auto& os_syscalls = Api::OsSysCallsSingleton::get();
  Api::SysCallIntResult status =
      os_syscalls.setsockopt(fd_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
  RELEASE_ASSERT(status.rc_ != -1, "failed to set SO_REUSEADDR socket option");
}

template <>
void NetworkListenSocket<
    NetworkSocketTrait<Address::SocketType::Datagram>>::setPrebindSocketOptions() {}

UdsListenSocket::UdsListenSocket(const Address::InstanceConstSharedPtr& address)
    : ListenSocketImpl(address->socket(Address::SocketType::Stream), address) {
  RELEASE_ASSERT(fd_ != -1, "");
  doBind();
}

UdsListenSocket::UdsListenSocket(int fd, const Address::InstanceConstSharedPtr& address)
    : ListenSocketImpl(fd, address) {}

} // namespace Network
} // namespace Envoy
<|endoftext|>