Mathematical Operations ============================= The following classes are all defined within the namespace ``HIPP::ALGORITHM``. .. namespace:: HIPP::ALGORITHM .. class:: OuterProduct .. function:: template\ static void indices(It b, It e, UnaryOp &&op) .. function:: template\ static void indices(It b, It e, UnaryOp &&op, ItStk it_stk) Outer product of index lists, i.e., :math:`(0,1,...,n_0-1)\times(0,1,...,n_1-1), ..., (0,1,...,n_{K-1}-1)`, where :math:`\times` is the Cartesian product. The result is an array of :math:`n=n_0 \times n_1 \times ... \times n_{K-1}` vectors. The size :math:`n` can be extremely large. To avoid significant memory consumption, the above functions do not return the results, but accept an operator which acts on each of the result vectors. **Arguments:** Template paramsters ``It`` and ``ItStk`` must be random accessible iterators referring to signed or unsigned integers. ``b`` and ``e`` define the upper limits of indices, i.e., the loop on the range ``[b, e)`` gives :math:`n_0, n_1, ..., n_{K-1}` (all must be positive), where ``e-b==K``. If ``b >= e``, the functions have no effect. ``op`` is the operator acting on each of the result vector. It is called as ``op(ptr)`` where ``ptr`` is a random access iterator referring to the first element of the result vector. In the first overload, ``ptr`` is a pointer to an array of elements with the same type as ``*b``. In the second overload, ``ptr`` is typed ``ItStk``. ``it_stk`` is a buffer. If provided, internal buffer allocation is avoided. The buffer length must be equal or large than ``max(e-b, 0)+1``. **Complexity:** The algorithm has a time complexity :math:`\mathcal{O}(n)`. In the first overload, a buffer sized ``K+1`` is allocated. In the second overload, no extra space is allocated. **Example:** .. code-block:: const int n = 2; int maxs[n] = {2, 3}; auto op = [n](int *p){ pout << '(', pout(p, p+n), ") "; }; OuterProduct::indices(maxs, maxs+n, op); Output are .. code-block:: text (0,0) (0,1) (0,2) (1,0) (1,1) (1,2) .. class:: template LinSpaced Produce linear-spaced values. Let :math:`s`, :math:`n`, :math:`\epsilon` to be the starting value, number of values and the stride, respectively, ``LinSpaced`` produces the following sequence .. math:: (s,\ s+\epsilon,\ s+2 \epsilon,\ ...,\ s+(n-1)\epsilon) .. type:: std::ptrdiff_t diff_t T value_t ``diff_t`` is used to represent the number of values. ``value_t`` is the type of result values. .. function:: LinSpaced(value_t start, diff_t n, value_t stride = value_t(1) ) noexcept Initialize the linear-spaced sequence by providing the starting value ``start``, number of values ``n`` and the stride ``stride``. The value sequence is not directly produced on the construction. To get the value sequence, call the following methods. .. function:: \ template\ const LinSpaced & operator>>(It b) const Write the sequence into a range started from the output iterator ``b``. .. function:: \ template\ const LinSpaced & get_to(Container &c) const Write the sequence into a container ``c``. ``clear()`` is called on ``c``, and values are written by ``push_back()`` into ``c``. .. function:: \ template >\ Container get() const Get the sequence of values. Defaultly it returns a ``std::vector``. .. _api-algorithm-linspaced-example: **Example:** The following codes show how to produce linear-spaced sequences:: int a[4]; double b[2][4]; vector c; /* write linearly-spaced values into an array */ LinSpaced(1, 4) >> a; pout << "Int Array: ", pout(a, a+4), endl; /* row-major writting is used for high-dimensional array */ LinSpaced(0., 8, 10.0) >> b[0]; pout << "Double Array:\n", PrtArray(b[0], b[0]+8).ncol(4).width(3), endl; /* get() returns a new vector. get_to() writes into an existing vector */ c = LinSpaced(float(0.), 4).get(); pout << "Float Vector: ", c, endl; LinSpaced(float(0.), 8).get_to(c); pout << "Float Vector: ", c, endl; /* write log-spaced values into vector */ LogSpaced(float(0.), 6, float(0.2)).get_to(c); pout << "Float Vector: ", c, endl; Here, values are printed into the "pretty stream" :var:`HIPP::pout` (similar to ``std::cout``). :class:`HIPP::PrtArray` is used to format the 2-d array. The output is .. code-block:: text Int Array: 1,2,3,4 Double Array: 0, 10, 20, 30, 40, 50, 60, 70 Float Vector: 0,1,2,3 Float Vector: 0,1,2,3,4,5,6,7 Float Vector: 1,1.58489,2.51189,3.98107,6.30957,10 .. class:: template LogSpaced Produce log10-spaced values. Let :math:`s`, :math:`n`, :math:`\epsilon` to be the starting value, number of values and the stride, respectively, ``LogSpaced`` produces the following sequence .. math:: (10^s,\ 10^{s+\epsilon},\ 10^{s+2 \epsilon},\ ...,\ 10^{s+(n-1)\epsilon}) .. type:: std::ptrdiff_t diff_t T value_t ``diff_t`` is used to represent the number of values. ``value_t`` is the type of result values. .. function:: \ LogSpaced(value_t start, diff_t n, value_t stride = value_t(1)) noexcept Initialize the log-spaced sequence by providing the starting value ``start``, number of values ``n`` and the stride ``stride``. The value sequence is not directly produced on the construction. To get the value sequence, call the following methods. .. function:: \ template\ const LogSpaced & operator>>(It b) const Write the sequence into a range started from the output iterator ``b``. .. function:: \ template \ const LogSpaced & get_to(Container &c) const Write the sequence into a container ``c``. ``clear()`` is called on ``c``, and values are written by ``push_back()`` into ``c``. .. function:: \ template > \ Container get() const Get the sequence of values. Defaultly it returns a ``std::vector``. **Example:** see the example in :ref:`LinSpaced `.