/* * Implementation of Kronecker product. * Eigen has an implementation of the Kronecker product, * but it is very slow due to poor memory reservation. * See: https://forum.kde.org/viewtopic.php?f=74&t=106955&p=309990&hilit=kronecker#p309990 * When Eigen update their implementation, and officially support it, we switch to that. */ SparseMatrix myKroneckerProduct(const SparseMatrix &A, const SparseMatrix &B) { SparseMatrix AB(A.rows()*B.rows(), A.cols()*B.cols()); // Reserve memory for AB //AB.reserve(A.nonZeros()*B.nonZeros()); // Does not reserve inner vectors (slow) //int innernnz = std::ceil(A.nonZeros()*B.nonZeros()/AB.outerSize()); //AB.reserve(Eigen::VectorXi::Constant(AB.outerSize(), innernnz)); // Assumes equal distribution of non-zeros (slow) // Calculate exact number of non-zeros for each inner vector Eigen::VectorXi nnzA = Eigen::VectorXi::Zero(A.outerSize()); Eigen::VectorXi nnzB = Eigen::VectorXi::Zero(B.outerSize()); Eigen::VectorXi nnzAB = Eigen::VectorXi::Zero(AB.outerSize()); //innerNonZeros.setZero(); for (int jA = 0; jA < A.outerSize(); ++jA) { int nnz = 0; for (SparseMatrix::InnerIterator itA(A,jA); itA; ++itA) nnz++; nnzA(jA) = nnz; } for (int jB = 0; jB < B.outerSize(); ++jB) { int nnz = 0; for (SparseMatrix::InnerIterator itB(B,jB); itB; ++itB) nnz++; nnzB(jB) = nnz; } int innz = 0; for (int i = 0; i < nnzA.rows(); ++i) { for (int j = 0; j < nnzB.rows(); ++j) { nnzAB(innz) = nnzA(i)*nnzB(j); innz++; } } AB.reserve(nnzAB); // Non-zero tolerance double tolerance = std::numeric_limits<SparseMatrix::Scalar>::epsilon(); // Compute Kronecker product for (int jA = 0; jA < A.outerSize(); ++jA) { for (SparseMatrix::InnerIterator itA(A,jA); itA; ++itA) { if (std::abs(itA.value()) > tolerance) { int jrow = itA.row()*B.rows(); int jcol = itA.col()*B.cols(); for (int jB = 0; jB < B.outerSize(); ++jB) { for (SparseMatrix::InnerIterator itB(B,jB); itB; ++itB) { if (std::abs(itA.value()*itB.value()) > tolerance) { int row = jrow + itB.row(); int col = jcol + itB.col(); AB.insert(row,col) = itA.value()*itB.value(); } } } } } } AB.makeCompressed(); return AB; }
/** * @brief Parses JSON data and assigns it to the given concert object * Handles all types of data from TMDb (info, releases, trailers, images) * @param json JSON data * @param concert Concert object * @param infos List of infos to load */ void TMDbConcerts::parseAndAssignInfos(QString json, Concert *concert, QList<int> infos) { qDebug() << "Entered"; QScriptValue sc; QScriptEngine engine; sc = engine.evaluate("(" + QString(json) + ")"); // Infos if (sc.property("imdb_id").isValid() && !sc.property("imdb_id").toString().isEmpty()) concert->setId(sc.property("imdb_id").toString()); if (infos.contains(ConcertScraperInfos::Title) && sc.property("title").isValid()) concert->setName(sc.property("title").toString()); if (infos.contains(ConcertScraperInfos::Overview) && sc.property("overview").isValid() && !sc.property("overview").isNull()) concert->setOverview(sc.property("overview").toString()); if (infos.contains(ConcertScraperInfos::Rating) && sc.property("vote_average").isValid()) concert->setRating(sc.property("vote_average").toNumber()); if (infos.contains(ConcertScraperInfos::Tagline) && sc.property("tagline").isValid() && !sc.property("tagline").isNull()) concert->setTagline(sc.property("tagline").toString()); if (infos.contains(ConcertScraperInfos::Released) && sc.property("release_date").isValid()) concert->setReleased(QDate::fromString(sc.property("release_date").toString(), "yyyy-MM-dd")); if (infos.contains(ConcertScraperInfos::Runtime) && sc.property("runtime").isValid()) concert->setRuntime(sc.property("runtime").toInteger()); if (infos.contains(ConcertScraperInfos::Genres) && sc.property("genres").isArray()) { QScriptValueIterator itC(sc.property("genres")); while (itC.hasNext()) { itC.next(); QScriptValue vC = itC.value(); if (vC.property("id").toString().isEmpty()) continue; concert->addGenre(vC.property("name").toString()); } } // Trailers if (infos.contains(ConcertScraperInfos::Trailer) && sc.property("youtube").isArray()) { QScriptValueIterator itC(sc.property("youtube")); while (itC.hasNext()) { itC.next(); QScriptValue vC = itC.value(); if (vC.property("source").toString().isEmpty()) continue; concert->setTrailer(QUrl(Helper::formatTrailerUrl(QString("http://www.youtube.com/watch?v=%1").arg(vC.property("source").toString())))); break; } } // Images if (infos.contains(ConcertScraperInfos::Backdrop) && sc.property("backdrops").isArray()) { QScriptValueIterator itB(sc.property("backdrops")); while (itB.hasNext()) { itB.next(); QScriptValue vB = itB.value(); if (vB.property("file_path").toString().isEmpty()) continue; Poster b; b.thumbUrl = m_baseUrl + "w780" + vB.property("file_path").toString(); b.originalUrl = m_baseUrl + "original" + vB.property("file_path").toString(); b.originalSize.setWidth(vB.property("width").toString().toInt()); b.originalSize.setHeight(vB.property("height").toString().toInt()); concert->addBackdrop(b); } } if (infos.contains(ConcertScraperInfos::Poster) && sc.property("posters").isArray()) { QScriptValueIterator itB(sc.property("posters")); while (itB.hasNext()) { itB.next(); QScriptValue vB = itB.value(); if (vB.property("file_path").toString().isEmpty()) continue; Poster b; b.thumbUrl = m_baseUrl + "w342" + vB.property("file_path").toString(); b.originalUrl = m_baseUrl + "original" + vB.property("file_path").toString(); b.originalSize.setWidth(vB.property("width").toString().toInt()); b.originalSize.setHeight(vB.property("height").toString().toInt()); concert->addPoster(b); } } // Releases if (infos.contains(ConcertScraperInfos::Certification) && sc.property("countries").isArray()) { QString locale; QString us; QString gb; QScriptValueIterator itB(sc.property("countries")); while (itB.hasNext()) { itB.next(); QScriptValue vB = itB.value(); if (vB.property("iso_3166_1").toString() == "US") us = vB.property("certification").toString(); if (vB.property("iso_3166_1").toString() == "GB") gb = vB.property("certification").toString(); if (vB.property("iso_3166_1").toString().toLower() == m_language) locale = vB.property("certification").toString(); } if (!locale.isEmpty()) concert->setCertification(locale); else if (!us.isEmpty()) concert->setCertification(us); else if (!gb.isEmpty()) concert->setCertification(gb); } }