File indexing completed on 2025-03-09 03:55:00

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 16/08/2016
0007  * Description : Vector operations methods for red eyes detection.
0008  *
0009  * SPDX-FileCopyrightText: 2016      by Omar Amin <Omar dot moh dot amin at gmail dot com>
0010  * SPDX-FileCopyrightText: 2016-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #ifndef DIGIKAM_VECTOR_OPERATIONS_H
0017 #define DIGIKAM_VECTOR_OPERATIONS_H
0018 
0019 // C++ includes
0020 
0021 #include <vector>
0022 
0023 // Qt includes
0024 
0025 #include <QtGlobal>
0026 
0027 namespace Digikam
0028 {
0029 
0030 template<class T>
0031 inline T length_squared(const std::vector<T>& diff)
0032 {
0033     T sum = 0;
0034 
0035     for (unsigned int i = 0 ; i < diff.size() ; ++i)
0036     {
0037         sum += diff[i] * diff[i];
0038     }
0039 
0040     return sum;
0041 }
0042 
0043 template<class T>
0044 std::vector<T> operator-(const std::vector<T>& v1, const std::vector<T>& v2)
0045 {
0046     Q_ASSERT(v1.size() == v2.size());
0047 
0048     std::vector<T> result(v1.size());
0049 
0050     for (unsigned int i = 0 ; i < v1.size() ; ++i)
0051     {
0052         result[i] = v1[i] - v2[i];
0053     }
0054 
0055     return result;
0056 }
0057 
0058 template<class T>
0059 std::vector<T> operator-(const std::vector<T>& v1)
0060 {
0061     std::vector<T> result(v1.size());
0062 
0063     for (unsigned int i = 0 ; i < v1.size() ; ++i)
0064     {
0065         result[i] = -v1[i];
0066     }
0067 
0068     return result;
0069 }
0070 
0071 template<class T>
0072 std::vector<T> operator/(const std::vector<T>& v1, int divisor)
0073 {
0074     std::vector<T> result(v1.size());
0075 
0076     for (unsigned int i = 0 ; i < v1.size() ; ++i)
0077     {
0078         result[i] = v1[i] / divisor;
0079     }
0080 
0081     return result;
0082 }
0083 
0084 template<class T>
0085 std::vector<std::vector<T> > operator/(const std::vector<std::vector<T> >& v1, int divisor)
0086 {
0087 /*
0088     Q_ASSERT(v1[0].size() != v2.size());
0089 */
0090     std::vector<std::vector<T> > result(v1.size(),std::vector<T>(v1[0].size(),0));
0091 
0092     for (unsigned int i = 0 ; i < v1.size() ; ++i)
0093     {
0094         for (unsigned int j = 0 ; j < v1[0].size() ; ++j)
0095         {
0096             result[i][j] = v1[i][j] / divisor;
0097         }
0098     }
0099 
0100     return result;
0101 }
0102 
0103 template<class T>
0104 std::vector<T> operator+(const std::vector<T>& v1, const std::vector<T>& v2)
0105 {
0106     Q_ASSERT(v1.size() == v2.size());
0107 
0108     std::vector<T> result(v1.size());
0109 
0110     for (unsigned int i = 0 ; i < v1.size() ; ++i)
0111     {
0112         result[i] = v1[i] + v2[i];
0113     }
0114 
0115     return result;
0116 }
0117 
0118 template<class T>
0119 std::vector<std::vector<T> > operator+(const std::vector<std::vector<T> >& v1,
0120                                        const std::vector<std::vector<T> >& v2)
0121 {
0122     Q_ASSERT((v1.size()    == v2.size())     &&
0123              (v1[0].size() == v2[0].size()));
0124 
0125     std::vector<std::vector<T> > result(v1.size(), std::vector<T>(v1[0].size(),0));
0126 
0127     for (unsigned int i = 0 ; i < v1.size() ; ++i)
0128     {
0129         for (unsigned int j = 0 ; j < v2[0].size() ; ++j)
0130         {
0131             result[i][j] += v1[i][j] + v2[i][j];
0132         }
0133 
0134     }
0135 
0136     return result;
0137 }
0138 
0139 template<class T>
0140 std::vector<T> operator*(const std::vector<std::vector<T> >& v1,
0141                          const std::vector<T>& v2)
0142 {
0143     Q_ASSERT(v1[0].size() == v2.size());
0144 
0145     std::vector<T> result(v1.size());
0146 
0147     for (unsigned int i = 0 ; i < v1.size() ; ++i)
0148     {
0149         result[i] = 0;
0150 
0151         for (unsigned int j = 0 ; j < v1[0].size() ; ++j)
0152         {
0153             result[i] += v1[i][j] * v2[j];
0154         }
0155     }
0156 
0157     return result;
0158 }
0159 
0160 template<class T>
0161 std::vector<std::vector<T> > operator*(const std::vector<std::vector<T> >& v1,
0162                                        const std::vector<std::vector<T> >& v2)
0163 {
0164     Q_ASSERT(v1[0].size() == v2.size());
0165 
0166     std::vector<std::vector<T> > result(v1.size(), std::vector<T>(v2[0].size(),0));
0167 
0168     for (unsigned int i = 0 ; i < v1.size() ; ++i)
0169     {
0170         for (unsigned int k = 0 ; k < v1[0].size() ; ++k)
0171         {
0172             // swapping j and k loops for cache optimization
0173 
0174             for (unsigned int j = 0 ; j < v2[0].size() ; ++j)
0175             {
0176 
0177                 result[i][j] += v1[i][k] * v2[k][j];
0178             }
0179         }
0180     }
0181 
0182     return result;
0183 }
0184 
0185 
0186 template<class T>
0187 std::vector<std::vector<T> > operator*(const std::vector<T>& v1,
0188                                        const std::vector<T>& v2)
0189 {
0190     Q_ASSERT(v1.size() == v2.size());
0191 
0192     std::vector<std::vector<T> > result(v1.size(), std::vector<T>(v2.size(), 0));
0193 
0194     for (unsigned int i = 0 ; i < v1.size() ; ++i)
0195     {
0196         for (unsigned int j = 0 ; j < v1.size() ; ++j)
0197         {
0198             result[i][j] = v1[i] * v2[j];
0199         }
0200     }
0201 
0202     return result;
0203 }
0204 
0205 template<class T>
0206 std::vector<std::vector<T> > operator+(const std::vector<std::vector<T> >& v1,
0207                                        float d)
0208 {
0209 /*
0210     Q_ASSERT((v1.size()    == v2.size())    &&
0211              (v1[0].size() == v2[0].size()));
0212 */
0213     std::vector<std::vector<T> > result(v1.size(), std::vector<T>(v1[0].size(), 0));
0214 
0215     for (unsigned int i = 0 ; i < v1.size() ; ++i)
0216     {
0217         for (unsigned int j = 0 ; j < v1[0].size() ; ++j)
0218         {
0219             result[i][j] = v1[i][j] * d;
0220         }
0221 
0222     }
0223 
0224     return result;
0225 }
0226 
0227 template<class T>
0228 std::vector<T> operator*(const std::vector<T>& v1,
0229                          float d)
0230 {
0231 /*
0232     Q_ASSERT((v1.size()    == v2.size())    &&
0233              (v1[0].size() == v2[0].size()));
0234 */
0235     std::vector<T> result(v1.size());
0236 
0237     for (unsigned int i = 0 ; i < v1.size() ; ++i)
0238     {
0239         result[i] = v1[i] * d;
0240 
0241     }
0242 
0243     return result;
0244 }
0245 
0246 } // namespace Digikam
0247 
0248 #endif // DIGIKAM_VECTOR_OPERATIONS_H