This file is indexed.

/usr/include/sopt/wavelets/sara.h is in libsopt-dev 2.0.0-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#ifndef SOPT_WAVELETS_SARA_H
#define SOPT_WAVELETS_SARA_H

#include "sopt/config.h"
#include <cmath>
#include <initializer_list>
#include <tuple>
#include <vector>
#include "sopt/logging.h"
#include "sopt/wavelets/wavelets.h"

namespace sopt {
namespace wavelets {

//! Sparsity Averaging Reweighted Analysis
class SARA : public std::vector<Wavelet> {
public:
#ifndef SOPT_HAS_NOT_USING
  // Constructors
  using std::vector<Wavelet>::vector;
#else
  //! Default constructor
  SARA() : std::vector<Wavelet>(){};
#endif
  //! Easy constructor
  SARA(std::initializer_list<std::tuple<std::string, t_uint>> const &init)
      : SARA(init.begin(), init.end()) {}
  //! Construct from any iterator over a (std:string, t_uint) tuple
  template <class ITERATOR,
            class T = typename std::
                enable_if<std::is_convertible<decltype(std::get<0>(*std::declval<ITERATOR>())),
                                              std::string>::value
                          and std::is_convertible<decltype(std::get<1>(*std::declval<ITERATOR>())),
                                                  t_uint>::value>::type>
  SARA(ITERATOR first, ITERATOR last) {
    for(; first != last; ++first)
      emplace_back(std::get<0>(*first), std::get<1>(*first));
  }
  //! Destructor
  virtual ~SARA() {}

  //! \brief Direct transform
  //! \param[in] signal: computes wavelet coefficients for this signal. Its size must be a
  //! multiple of $2^l$ where $l$ is the maximum number of levels. Can be a matrix (2d-transform)
  //! or a column vector (1-d transform).
  //! \return wavelets coefficients arranged by columns: if the input is n by m, then the output
  //! is n by m * d, with d the number of wavelets.
  //! \details Supports 1 and 2 dimensional tranforms for real and complex data.
  template <class T0> typename T0::PlainObject direct(Eigen::ArrayBase<T0> const &signal) const;
  //! \brief Direct transform
  //! \param[inout] coefficients: Output wavelet coefficients. Must be of the type as the input.
  //! If the input is n by m, and d is the number of wavelets, then the output should be n by (m *
  //! d).
  //! \param[in] signal: computes wavelet coefficients for this signal. Its size must be a
  //! multiple of $2^l$ where $l$ is the maximum number of levels. Can be a matrix (2d-transform)
  //! or a column vector (1-d transform).
  //! \details Supports 1 and 2 dimensional tranforms for real and complex data.
  template <class T0, class T1>
  void direct(Eigen::ArrayBase<T1> &coefficients, Eigen::ArrayBase<T0> const &signal) const;
  //! \brief Direct transform
  //! \param[inout] coefficients: Output wavelet coefficients. Must be of the type as the input.
  //! If the input is n by m, and l is the number of wavelets, then the output should be n by (m *
  //! l).
  //! \param[in] signal: computes wavelet coefficients for this signal. Its size must be a
  //! multiple of $2^l$ where $l$ is the number of levels. Can be a matrix (2d-transform) or a
  //! column vector (1-d transform).
  //! \details Supports 1 and 2 dimensional tranforms for real and complex data. This version
  //! allows non-constant Eigen expressions to be passe on without the ugly `const_cast` of the
  //! cannonical approach.
  template <class T0, class T1>
  void direct(Eigen::ArrayBase<T1> &&coefficients, Eigen::ArrayBase<T0> const &signal) const {
    direct(coefficients, signal);
  }
  //! \brief Indirect transform
  //! \param[in] coefficients: Input wavelet coefficients. Its size must be a multiple of $2^l$
  //! where $l$ is the number of levels. Can be a matrix (2d-transform) or a column vector (1-d
  //! transform).
  //! \details Supports 1 and 2 dimensional tranforms for real and complex data.
  template <class T0> typename T0::PlainObject indirect(Eigen::ArrayBase<T0> const &coeffs) const;
  //! \brief Indirect transform
  //! \param[in] coefficients: Input wavelet coefficients. Its size must be a multiple of $2^l$
  //! where $l$ is the number of levels. Can be a matrix (2d-transform) or a column vector (1-d
  //! \param[inout] signal: Reconstructed signal. Must be of the same size and type as the input.
  //! \details Supports 1 and 2 dimensional tranforms for real and complex data.
  template <class T0, class T1>
  void indirect(Eigen::ArrayBase<T1> const &coefficients, Eigen::ArrayBase<T0> &signal) const;
  //! \brief Indirect transform
  //! \param[in] coefficients: Input wavelet coefficients. Its size must be a multiple of $2^l$
  //! where $l$ is the number of levels. Can be a matrix (2d-transform) or a column vector (1-d
  //! \param[inout] signal: Reconstructed signal. Must be of the same size and type as the input.
  //! \details Supports 1 and 2 dimensional tranforms for real and complex data.  This version
  //! allows non-constant Eigen expressions to be passe on without the ugly `const_cast` of the
  //! cannonical approach.
  template <class T0, class T1>
  void indirect(Eigen::ArrayBase<T1> const &coeffs, Eigen::ArrayBase<T0> &&signal) const {
    indirect(coeffs, signal);
  }

  //! Number of levels over which to do transform
  t_uint max_levels() const {
    auto cmp = [](Wavelet const &a, Wavelet const &b) { return a.levels() < b.levels(); };
    return std::max_element(begin(), end(), cmp)->levels();
  }

  //! Adds a wavelet of specific type
  void emplace_back(std::string const &name, t_uint nlevels) {
    std::vector<Wavelet>::emplace_back(factory(name, nlevels));
  }
};

#define SOPT_WAVELET_ERROR_MACRO(INPUT)                                                            \
  if(INPUT.rows() % (1u << max_levels()) != 0)                                                     \
    throw std::length_error("Inconsistent number of columns and wavelet levels");                  \
  else if(INPUT.cols() != 1 and INPUT.cols() % (1u << max_levels()))                               \
    throw std::length_error("Inconsistent number of rows and wavelet levels");

template <class T0, class T1>
void SARA::direct(Eigen::ArrayBase<T1> &coeffs, Eigen::ArrayBase<T0> const &signal) const {
  SOPT_WAVELET_ERROR_MACRO(signal);
  if(coeffs.rows() != signal.rows() or coeffs.cols() != signal.cols() * static_cast<t_int>(size()))
    coeffs.derived().resize(signal.rows(), signal.cols() * size());
  if(coeffs.rows() != signal.rows() or coeffs.cols() != signal.cols() * static_cast<t_int>(size()))
    throw std::length_error("Incorrect size for output matrix(or could not resize)");
  auto const Ncols = signal.cols();
#ifndef SOPT_OPENMP
  SOPT_TRACE("Calling direct sara without threads");
  for(size_type i(0); i < size(); ++i)
    at(i).direct(coeffs.leftCols((i + 1) * Ncols).rightCols(Ncols), signal);
#else
#pragma omp parallel
  {
    if(omp_get_thread_num() == 0) {
      SOPT_TRACE("Calling direct sara with {} threads of {}", omp_get_num_threads(),
                 omp_get_max_threads());
    }
#pragma omp for
    for(size_type i = 0; i < size(); ++i)
      at(i).direct(coeffs.leftCols((i + 1) * Ncols).rightCols(Ncols), signal);
  }
#endif
  coeffs /= std::sqrt(size());
}

template <class T0, class T1>
void SARA::indirect(Eigen::ArrayBase<T1> const &coeffs, Eigen::ArrayBase<T0> &signal) const {
  SOPT_WAVELET_ERROR_MACRO(coeffs);
  if(coeffs.cols() % size() != 0)
    throw std::length_error(
        "Columns of coefficient matrix and number of wavelets are inconsistent");
  if(coeffs.rows() != signal.rows() or coeffs.cols() != signal.cols() * static_cast<t_int>(size()))
    signal.derived().resize(coeffs.rows(), coeffs.cols() / size());
  if(coeffs.rows() != signal.rows() or coeffs.cols() != signal.cols() * static_cast<t_int>(size()))
    throw std::length_error("Incorrect size for output matrix(or could not resize)");

  auto const Ncols = signal.cols();
#ifndef SOPT_OPENMP
  SOPT_TRACE("Calling indirect sara without threads");
  signal = front().indirect(coeffs.leftCols(Ncols).rightCols(Ncols));
  for(size_type i(1); i < size(); ++i)
    signal += at(i).indirect(coeffs.leftCols((i + 1) * Ncols).rightCols(Ncols));
#else
  signal.fill(0);
#pragma omp parallel
  {
    if(omp_get_thread_num() == 0) {
      SOPT_TRACE("Calling indirect sara with {} threads of {}", omp_get_num_threads(),
                 omp_get_max_threads());
    }
    Image<typename T0::Scalar> reductor = Image<typename T0::Scalar>::Zero(signal.rows(), Ncols);
#pragma omp for
    for(size_type i = 0; i < size(); ++i)
      reductor += at(i).indirect(coeffs.leftCols((i + 1) * Ncols).rightCols(Ncols));
#pragma omp critical
    signal += reductor;
  }
#endif
  signal /= std::sqrt(size());
}

#undef SOPT_WAVELET_ERROR_MACRO

template <class T0>
typename T0::PlainObject SARA::indirect(Eigen::ArrayBase<T0> const &coeffs) const {
  typedef decltype(this->front().indirect(coeffs)) t_Output;
  t_Output signal = t_Output::Zero(coeffs.rows(), coeffs.cols() / size());
  (*this).indirect(coeffs, signal);
  return signal;
}

template <class T0>
typename T0::PlainObject SARA::direct(Eigen::ArrayBase<T0> const &signal) const {
  typedef decltype(this->front().direct(signal)) t_Output;
  t_Output result = t_Output::Zero(signal.rows(), signal.cols() * size());
  (*this).direct(result, signal);
  return result;
}
}
}
#endif