One more circular buffer(normal queue)

One more circular buffer(normal queue)

Sometimes we prefer to use circular buffer: “like CircularBuffer, but NOT use size and next index, but use front and rear”, so an impletametation here.

See also
Write a CircularBuffer
std::queue
Full impletametation: circularqueue.hpp

/**
 * Var capacity circular queue.
 * NOTE:
 * - Like CircularBuffer, but if full, enque(push) will FAIL!
 * - And like CircularBuffer, but NOT use size and next index, but use front
 *   and rear.
 * - When use in multi-threads, should add lock or some other to sync.
 * @tparam T data type.
 * @sa CircularBuffer
 * @todo
 * - Add full CircularBuffer like features.
 * - Add iterators.
 */
template<typename T>
class CircularQueue {
public:
    /**
     * Ctor.
     * @param capacity the buffer capacity, should >= 1.
     * @throw std::logic_error when capacity invalid.
     */
    CircularQueue(int32_t capacity = 1, const T& initValue = T{});
    /**
     * Test whether container is empty
     * @return True if queue is empty, false otherwise.
     */
    inline bool empty() const noexcept;
    /**
     * Test whether container is empty
     * @return True if queue if full, false otherwise.
     */
    inline bool full() const noexcept;
    /// @return data size.
    inline int32_t size() const noexcept;
    /// @return queue capacity.
    inline int32_t capacity() const noexcept;
    /**
     * Inserts a new element at the end of the queue, after its current last
     * element. The content of this new element is initialized to value.
     * @param value Value to which the inserted element is initialized.
     * Member type value_type is the type of the elements in the container
     * (defined as an alias of the first class template parameter, T).
     */
    bool push(const T& value) noexcept;
    bool push(T&& value) noexcept;
    bool pop() noexcept;
    bool pop(T& value) noexcept;
    /// @throw std::logic_error when queue empty.
    T pop_front();
    /**
     * Get queue head(front) when not empty.
     * @return queue head(front) when not empty.
     * @throw std::logic_error when empty.
     */
    const T& front() const;
    T& front();
private:
    /// Pop index(current or next readable), init as empty.
    int32_t currRFront{ -1 };
    int32_t lastWRear{ -1 };///< Push index(last writeable), init as empty
    int32_t capa{ 1 };///< The buffer capacity, > 0.
    std::vector<T> buffer;///< The internal buffer.
};

不易理解的指针(C/C++)

不易理解的指针(C/C++)

See also


#include <iostream>

/**
 * 不易理解的指针:
 *
 * - 函数指针
 * - 指针数组
 * - 数组指针
 * - 返回函数指针的函数
 *
 * Compile:
 * g++ pointer.cpp -std=c++11 -Wall -Wextra
 *
 * @note better NOT function pointer, but use C++ functor if you can, e.g.
 * std::function
 * boost::function
 */

int main() noexcept
{
    // 函数指针和(函数)指针数组
    int (* a1[10])(int) = { nullptr };// The array of 10 function pointers, init [0] to nullptr, others 0
    // ERROR: int (error1[10])(int) = { nullptr };
    int* a2[10] = { nullptr };// The array of 10 int pointers, init [0] to nullptr, others 0
    std::cout << std::is_array<decltype(a2)>::value << '\n';// 1

    typedef int (function_t)(int);// Functor type
    typedef int function2_t(int);// Functor type
    int (foo)(int);// 函数声明
    typedef int (* functionptr_t)(int);// Functor pointer type (函数指针类型)
    // Another array of 10 function pointers, init [0] and [1] to nullptr, others 0
    function_t* a4[10] = { nullptr, nullptr };
    functionptr_t a5[10] = { nullptr, nullptr };

    std::cout << std::is_same<function_t, function2_t>::value << '\n';// 1
    std::cout << std::is_same<decltype(a1), decltype(a4)>::value << '\n';// 1
    std::cout << std::is_same<decltype(a1), decltype(a5)>::value << '\n';// 1

    int (* a3)(int) = nullptr;// 函数指针
    function_t* a6 = nullptr;// 函数指针
    functionptr_t a7 = nullptr;// 函数指针
    std::cout << std::is_same<decltype(a3), decltype(a6)>::value << '\n';// 1
    std::cout << std::is_same<decltype(a3), decltype(a7)>::value << '\n';// 1

    // 数组指针
    function_t* (* b1)[10] = nullptr;// The pointer of an array of 10 function pointers: b1
    // ERROR: function_t (*error2)[10] = nullptr;
    functionptr_t (* b2)[10] = nullptr;// The pointer of an array of 10 function pointers: b2
    typedef function_t* functionptrarr_t[10];// The array type of array of function pointers
    typedef functionptr_t functionptrarr2_t[10];// The array type of array of function pointers
    functionptrarr_t* b3 = nullptr;// 数组指针
    functionptrarr2_t* b4 = nullptr;// 数组指针
    b4 = b3 = b2 = b1;// OK
    std::cout << std::is_same<decltype(b1), decltype(b2)>::value << '\n';// 1
    std::cout << std::is_same<decltype(b1), decltype(b3)>::value << '\n';// 1
    std::cout << std::is_same<decltype(b1), decltype(b4)>::value << '\n';// 1
    int (* b5)[10] = nullptr;// The pointer of an array of 10 int pointers: b5
    typedef int intarr_t[10];// The array type of array of 10 int pointers
    intarr_t* b6 = nullptr;// 数组指针
    b6 = b5;// OK
    std::cout << std::is_same<decltype(b5), decltype(b6)>::value << '\n';// 1
    std::cout << std::is_array<decltype(b1)>::value << '\n';// 0

    // 返回函数指针的函数
    // foo2 是一个函数(声明), 该函数的参数是第一个 int 型, 第二个 char* 型,
    // 该函数返回值的是一个函数指针(对象),
    // 这个函数指针(指向的函数)的类型是 int 型返回值和一个 int 型参数.
    int (* foo2(int, char*))(int);
    // 即上面等价于:
    typedef int foo_t(int);
    foo_t* foo3(int, char*);
    std::cout << std::is_same<decltype(foo2), decltype(foo3)>::value << '\n';// 1

    return 0;
}

GNU libc Rounding Functions

GNU libc Rounding Functions

See also http://www.gnu.org/software/libc/manual/html_node/Rounding-Functions.html

The functions listed here perform operations such as rounding and truncation
of floating-point values. Some of these functions convert floating point
numbers to integer values. They are all declared in math.h.

You can also convert floating-point numbers to integers simply by casting
them to int. This discards the fractional part
, effectively rounding towards
zero.
However, this only works if the result can actually be represented as an
int-for very large numbers, this is impossible.
The functions listed here return the result as a double instead to get around
this problem.

The fromfp functions use the following macros, from TS 18661-1:2014, to
specify the direction of rounding.
These correspond to the rounding directions defined in IEEE 754-2008.

trunc

The trunc functions round x towards zero to the nearest integer
(returned in floating-point format). Thus,
trunc (1.5) is 1.0 and trunc (-1.5) is -1.0 (丢掉小数部分, x 大于等于 0 的时候结果
等于 floor(x), x 小于等于 0 的时候结果等于 ceil(x)
).

ceil

These functions round x upwards to the nearest integer, returning that value
as a double. Thus, ceil (1.5) is 2.0 (ceil: 天花板 — 向上(大)取整).

floor

These functions round x downwards to the nearest integer, returning that value
as a double. Thus, floor (1.5) is 1.0 and floor (-1.5) is -2.0 (
floor: 地板 — 向下(小)取整).

round

These functions are similar to rint, but they round halfway cases(一半的情况)
away from zero instead of to the nearest integer
(or other current rounding mode).
I.e. round to nearest integer, away from zero (返回 四舍五入整数).

rint

These functions round x to an integer value according to the current rounding
mode, usually 1, example 2.23-0ubuntu11 libc, gcc 5.4.0: FLT_ROUNDS is 1:

/usr/lib/gcc/x86_64-linux-gnu/5/include/float.h:128:

/* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown.  */
/* ??? This is supposed to change with calls to fesetround in <fenv.h>.  */
#undef FLT_ROUNDS
#define FLT_ROUNDS 1

And:

BUGS
       C99 specifies that the value of FLT_ROUNDS should reflect changes
       to the current rounding mode, as set by fesetround().  Currently,
       this does not occur: FLT_ROUNDS always has the value 1.

See also http://www.gnu.org/software/libc/manual/html_node/Floating-Point-Parameters.html#Floating-Point-Parameters

Round to nearest integer (Like round, but maybe NOT good, better use round
when nearest integer, especially “四舍五入”
, rint 返回 最接近参数的整数,
如果有两个数同样接近, 则会返回偶数的那个 !!
).

Bad rint examples

EXPECT_DOUBLE_EQ(-2.0, ::rint(-1.5));
EXPECT_DOUBLE_EQ(-2.0, ::rint(-2.5));// Here we want -3.0!
EXPECT_DOUBLE_EQ(0.0, ::rint(0.5));// Here we want 1.0!
EXPECT_DOUBLE_EQ(0.0, ::rint(-0.5));// Here we want -1.0!

Good round examples

EXPECT_DOUBLE_EQ(-2.0, ::round(-1.5));
EXPECT_DOUBLE_EQ(-3.0, ::round(-2.5));// Here we want -3.0!
EXPECT_DOUBLE_EQ(1.0, ::round(0.5));// Here we want 1.0!
EXPECT_DOUBLE_EQ(-1.0, ::round(-0.5));// Here we want -1.0!

对比

value round rint floor ceil trunc
0.1 0.0 0.0 0.0 1.0 0.0
0.5 1.0 0.0 0.0 1.0 0.0
0.6 1.0 1.0 0.0 1.0 0.0
1.1 1.0 1.0 1.0 2.0 1.0
1.5 2.0 2.0 1.0 2.0 1.0
2.3 2.0 2.0 2.0 3.0 2.0
2.5 3.0 2.0 2.0 3.0 2.0
3.8 4.0 4.0 3.0 4.0 3.0
5.5 6.0 6.0 5.0 6.0 5.0
-0.5 -1.0 -0.0 -1.0 -0.0 -0.0
-1.1 -1.0 -1.0 -2.0 -1.0 -1.0
-1.5 -2.0 -2.0 -2.0 -1.0 -1.0
-2.3 -2.0 -2.0 -3.0 -2.0 -2.0
-2.5 -3.0 -2.0 -3.0 -2.0 -2.0
-3.8 -4.0 -4.0 -4.0 -3.0 -3.0
-5.5 -6.0 -6.0 -6.0 -5.0 -5.0

See also