Init
This commit is contained in:
commit
1dd80d61bf
|
@ -0,0 +1,169 @@
|
|||
# Created by https://www.toptal.com/developers/gitignore/api/clion,cmake,c++
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=clion,cmake,c++
|
||||
|
||||
### C++ ###
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
### CLion ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# AWS User-specific
|
||||
.idea/**/aws.xml
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/artifacts
|
||||
# .idea/compiler.xml
|
||||
# .idea/jarRepositories.xml
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
# *.iml
|
||||
# *.ipr
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# SonarLint plugin
|
||||
.idea/sonarlint/
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
### CLion Patch ###
|
||||
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
|
||||
|
||||
# *.iml
|
||||
# modules.xml
|
||||
# .idea/misc.xml
|
||||
# *.ipr
|
||||
|
||||
# Sonarlint plugin
|
||||
# https://plugins.jetbrains.com/plugin/7973-sonarlint
|
||||
.idea/**/sonarlint/
|
||||
|
||||
# SonarQube Plugin
|
||||
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
|
||||
.idea/**/sonarIssues.xml
|
||||
|
||||
# Markdown Navigator plugin
|
||||
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
|
||||
.idea/**/markdown-navigator.xml
|
||||
.idea/**/markdown-navigator-enh.xml
|
||||
.idea/**/markdown-navigator/
|
||||
|
||||
# Cache file creation bug
|
||||
# See https://youtrack.jetbrains.com/issue/JBR-2257
|
||||
.idea/$CACHE_FILE$
|
||||
|
||||
# CodeStream plugin
|
||||
# https://plugins.jetbrains.com/plugin/12206-codestream
|
||||
.idea/codestream.xml
|
||||
|
||||
# Azure Toolkit for IntelliJ plugin
|
||||
# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
|
||||
.idea/**/azureSettings.xml
|
||||
|
||||
### CMake ###
|
||||
CMakeLists.txt.user
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
CMakeScripts
|
||||
Testing
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
compile_commands.json
|
||||
CTestTestfile.cmake
|
||||
_deps
|
||||
|
||||
### CMake Patch ###
|
||||
# External projects
|
||||
*-prefix/
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/clion,cmake,c++
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
|
@ -0,0 +1 @@
|
|||
GTI320-labos
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module classpath="CMake" type="CPP_MODULE" version="4" />
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||
</project>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/Lab1.iml" filepath="$PROJECT_DIR$/.idea/Lab1.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,32 @@
|
|||
cmake_minimum_required(VERSION 3.15)
|
||||
project(GTI320-labos)
|
||||
|
||||
#--------------------------------------------------
|
||||
# Add google test and setup build
|
||||
#--------------------------------------------------
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
GIT_TAG release-1.11.0
|
||||
)
|
||||
|
||||
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
|
||||
# No need for GMock
|
||||
set( BUILD_GMOCK OFF CACHE BOOL "" FORCE)
|
||||
set( INSTALL_GTEST OFF CACHE BOOL "" FORCE)
|
||||
set( GTEST_FORCE_SHARED_CRT ON CACHE BOOL "" FORCE)
|
||||
set( GTEST_DISABLE_PTHREADS ON CACHE BOOL "" FORCE)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
||||
add_subdirectory(labo01)
|
||||
|
||||
# TODO add nanogui setup and labo 02 and labo 03
|
||||
|
||||
if( MSVC )
|
||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT labo01)
|
||||
endif()
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
project(labo01)
|
||||
|
||||
# Setup language requirements
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# Add .cpp and .h files
|
||||
set(HEADERS DenseStorage.h MatrixBase.h Matrix.h Math3D.h Vector.h Operators.h)
|
||||
set(SOURCE main.cpp)
|
||||
add_executable(labo01 ${SOURCE} ${HEADERS})
|
||||
|
||||
# Add linking information for Google Test
|
||||
target_link_libraries(labo01 gtest)
|
||||
|
||||
# Set labo01 as the startup project for Visual Studio
|
||||
if( MSVC )
|
||||
set_property(TARGET labo01 PROPERTY VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/labo01)
|
||||
endif()
|
||||
|
|
@ -0,0 +1,217 @@
|
|||
#pragma once
|
||||
|
||||
/**
|
||||
* @file DenseStorage.h
|
||||
*
|
||||
* @brief Stockage dense pour des données à taille fixe ou dynamique.
|
||||
*
|
||||
* Nom:
|
||||
* Code permanent :
|
||||
* Email :
|
||||
*
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
namespace gti320
|
||||
{
|
||||
enum SizeType { Dynamic = -1 };
|
||||
|
||||
/**
|
||||
* Stockage à taille fixe.
|
||||
*
|
||||
* Le nombre de données à stocker est connu au moment de la compilation.
|
||||
* Ce nombre est donné par le paramètre de patron : _Size
|
||||
*
|
||||
* Un tampon (tableau) de taille `_Size_` est alloué sur la pile d'exécution.
|
||||
*/
|
||||
template<typename _Scalar, int _Size>
|
||||
class DenseStorage
|
||||
{
|
||||
private:
|
||||
|
||||
// TODO déclarer une variable m_data et allouer la mémoire pour y stocker _Size éléments
|
||||
_Scalar* m_data; // <-- Ceci n'est pas bon, à modifier
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructeur par défaut
|
||||
*/
|
||||
DenseStorage() { }
|
||||
|
||||
/**
|
||||
* Constructeur de copie
|
||||
*/
|
||||
DenseStorage(const DenseStorage& other)
|
||||
{
|
||||
memcpy(m_data, other.m_data, sizeof(m_data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec taille spécifiée
|
||||
*
|
||||
* (doit être la même que la taille spécifiée dans le patron)
|
||||
*/
|
||||
explicit DenseStorage(int _size) { }
|
||||
|
||||
/**
|
||||
* Constructor avec taille (_size) et données initiales (_data).
|
||||
*/
|
||||
explicit DenseStorage(const _Scalar* _data, int _size)
|
||||
{
|
||||
assert(_size >= 0 && _size == _Size);
|
||||
memcpy(m_data, _data, sizeof(_Scalar) * _size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opérateur de copie
|
||||
*/
|
||||
DenseStorage& operator=(const DenseStorage& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
assert(other.size() == _Size);
|
||||
memcpy(m_data, other.m_data, sizeof(m_data));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
static int size() { return _Size; }
|
||||
|
||||
/**
|
||||
* Redimensionne le stockage pour qu'il contienne `size` élément.
|
||||
*/
|
||||
void resize(int size)
|
||||
{
|
||||
// Ne rien faire. Invalide pour les matrices à taille fixe.
|
||||
}
|
||||
|
||||
/**
|
||||
* Mets tous les éléments à zéro.
|
||||
*/
|
||||
void setZero()
|
||||
{
|
||||
memset(m_data, 0, sizeof(_Scalar) * _Size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accès au tampon de données (en lecteur seulement)
|
||||
*/
|
||||
const _Scalar* data() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accès au tampon de données (pour lecture et écriture)
|
||||
*/
|
||||
_Scalar* data()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Stockage à taille dynamique.
|
||||
*
|
||||
* Le nombre de données à stocker est déterminé à l'exécution.
|
||||
* Un tampon de la taille demandée doit être alloué sur le tas via
|
||||
* l'opérateur `new []` et la mémoire doit être libérée avec `delete[]`
|
||||
*/
|
||||
template<typename _Scalar>
|
||||
class DenseStorage<_Scalar, Dynamic>
|
||||
{
|
||||
private:
|
||||
_Scalar* m_data;
|
||||
int m_size;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructeur par défaut
|
||||
*/
|
||||
DenseStorage() : m_data(nullptr), m_size(0) {}
|
||||
|
||||
/**
|
||||
* Constructeur avec taille spécifiée
|
||||
*/
|
||||
explicit DenseStorage(int _size) : m_data(nullptr), m_size(_size)
|
||||
{
|
||||
// TODO allouer un tampon pour stocker _size éléments de type _Scalar.
|
||||
|
||||
// TODO initialiser ce tampon à zéro.
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur de copie
|
||||
*/
|
||||
DenseStorage(const DenseStorage& other)
|
||||
: m_data(nullptr)
|
||||
, m_size(other.m_size)
|
||||
{
|
||||
// TODO allouer un tampon pour stocker _size éléments de type _Scalar.
|
||||
|
||||
// TODO copier other.m_data dans m_data.
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Opérateur de copie
|
||||
*/
|
||||
DenseStorage& operator=(const DenseStorage& other)
|
||||
{
|
||||
// TODO implémenter !
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructeur
|
||||
*/
|
||||
~DenseStorage()
|
||||
{
|
||||
// TODO libérer la mémoire allouée
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la taille du tampon
|
||||
*/
|
||||
inline int size() const { return m_size; }
|
||||
|
||||
/**
|
||||
* Redimensionne le tampon alloué pour le stockage.
|
||||
* La mémoire qui n'est plus utilisée doit être libérée.
|
||||
*
|
||||
* Note : Toutes opérations de redimensionnement entraînent une réallocation de mémoire.
|
||||
* Il n’est pas pertinent de copier les données car le résultat serait de toute façon incohérent.
|
||||
*/
|
||||
void resize(int _size)
|
||||
{
|
||||
// TODO redimensionner la mémoire allouée
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Met tous les éléments à zéro.
|
||||
*/
|
||||
void setZero()
|
||||
{
|
||||
// TODO implémenter !
|
||||
}
|
||||
|
||||
/**
|
||||
* Accès au tampon de données (en lecteur seulement)
|
||||
*/
|
||||
const _Scalar* data() const { return m_data; }
|
||||
|
||||
/**
|
||||
* Accès au tampon de données (pour lecture et écriture)
|
||||
*/
|
||||
_Scalar* data() { return m_data; }
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
#pragma once
|
||||
|
||||
/**
|
||||
* @file Math3D.h
|
||||
*
|
||||
* @brief Fonctions pour l'intinialisation et la manipulation de matrices de
|
||||
* rotation, des matrices de transformations en coordonnées homogènes et les
|
||||
* vecteurs 3D.
|
||||
*
|
||||
* Nom:
|
||||
* Code permanent :
|
||||
* Email :
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Matrix.h"
|
||||
#include "Vector.h"
|
||||
#include "Operators.h"
|
||||
|
||||
#ifndef _USE_MATH_DEFINES
|
||||
#define _USE_MATH_DEFINES
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
||||
namespace gti320 {
|
||||
|
||||
// Deux types de vecteurs 3D considérés ici
|
||||
typedef Vector<double, 3> Vector3d;
|
||||
typedef Vector<float, 3> Vector3f;
|
||||
|
||||
// Dans le cadre de ce projet, nous considérons seulement deux
|
||||
// cas :
|
||||
//
|
||||
// - les rotations
|
||||
// - les translations
|
||||
//
|
||||
// Deux types de matrices en coordonnées homogèes :
|
||||
typedef Matrix<double, 4, 4, ColumnStorage> Matrix4d;
|
||||
typedef Matrix<float, 4, 4, ColumnStorage> Matrix4f;
|
||||
//
|
||||
// Deux types de matrices pour les rotations
|
||||
typedef Matrix<double, 3, 3, ColumnStorage> Matrix3d;
|
||||
typedef Matrix<float, 3, 3, ColumnStorage> Matrix3f;
|
||||
|
||||
/**
|
||||
* Initialise et retourne la matrice identité
|
||||
*/
|
||||
template<>
|
||||
inline void Matrix4d::setIdentity()
|
||||
{
|
||||
// TODO affecter la valeur 0.0 partout, sauf sur la diagonale principale où c'est 1.0.
|
||||
// Note: ceci est une redéfinition d'une fonction membre!
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcul de la matrice inverse, SPÉCIALISÉ pour le cas d'une matrice de
|
||||
* transformation en coordonnées homogènes.
|
||||
*
|
||||
* TODO (vous pouvez supposer qu'il s'agit d'une matrice de transformation
|
||||
* en coordonnées homogènes)
|
||||
*/
|
||||
template<>
|
||||
inline Matrix4d Matrix4d::inverse() const
|
||||
{
|
||||
// TODO : implémenter
|
||||
return Matrix4d(); // Pas bon, à changer
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcul de la matrice inverse, SPÉCIALISÉ pour le cas d'une matrice de rotation.
|
||||
*
|
||||
* (vous pouvez supposer qu'il s'agit d'une matrice de rotation)
|
||||
*/
|
||||
template<>
|
||||
inline Matrix3d Matrix3d::inverse() const
|
||||
{
|
||||
// TODO : implémenter
|
||||
return Matrix3d();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Multiplication d'une matrice 4x4 avec un vecteur 3D où la matrice
|
||||
* représente une transformation en coordonnées homogène.
|
||||
*/
|
||||
template <typename _Scalar>
|
||||
Vector<_Scalar, 3> operator*(const Matrix<_Scalar, 4, 4, ColumnStorage>& A, const Vector<_Scalar, 3>& v)
|
||||
{
|
||||
// TODO : implémenter
|
||||
return Vector<_Scalar, 3>(); // pas bon, à changer
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialise et retourne la matrice de rotation définie par les angles
|
||||
* d'Euler XYZ exprimés en radians.
|
||||
*
|
||||
* La matrice doit correspondre au produit : Rz*Ry*Rx.
|
||||
*/
|
||||
template<typename _Scalar>
|
||||
static Matrix<_Scalar, 3, 3> makeRotation(_Scalar x, _Scalar y, _Scalar z)
|
||||
{
|
||||
// TODO : implémenter
|
||||
|
||||
return Matrix<_Scalar, 3, 3>(); // pas bon, à changer
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,343 @@
|
|||
#pragma once
|
||||
|
||||
/**
|
||||
* @file Matrix.h
|
||||
*
|
||||
* @brief Implémentation de matrices simples.
|
||||
*
|
||||
* Nom:
|
||||
* Code permanent :
|
||||
* Email :
|
||||
*
|
||||
*/
|
||||
|
||||
#include "MatrixBase.h"
|
||||
|
||||
namespace gti320
|
||||
{
|
||||
enum StorageType
|
||||
{
|
||||
ColumnStorage = 0,
|
||||
RowStorage = 1
|
||||
};
|
||||
|
||||
// Déclaration avancée
|
||||
template <typename _Scalar, int _RowsAtCompile, int _ColsAtCompile, int _StorageType> class SubMatrix;
|
||||
|
||||
/**
|
||||
* Classe Matrix spécialisé pour le cas générique. (defaut par colonne)
|
||||
*
|
||||
* (le cas d'un stockage par ligne fait l'objet d'une spécialisation de patron, voir plus bas)
|
||||
*/
|
||||
template <typename _Scalar = double, int _RowsAtCompile = Dynamic, int _ColsAtCompile = Dynamic, int _StorageType = ColumnStorage>
|
||||
class Matrix : public MatrixBase<_Scalar, _RowsAtCompile, _ColsAtCompile> {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructeur par défaut
|
||||
*/
|
||||
Matrix() : MatrixBase<_Scalar, _RowsAtCompile, _ColsAtCompile>() { }
|
||||
|
||||
/**
|
||||
* Constructeur de copie
|
||||
*/
|
||||
Matrix(const Matrix& other) : MatrixBase<_Scalar, _RowsAtCompile, _ColsAtCompile>(other) { }
|
||||
|
||||
/**
|
||||
* Constructeur avec spécification du nombre de ligne et de colonnes
|
||||
*/
|
||||
explicit Matrix(int _rows, int _cols) : MatrixBase<_Scalar, _RowsAtCompile, _ColsAtCompile>(_rows, _cols) { }
|
||||
|
||||
/**
|
||||
* Destructeur
|
||||
*/
|
||||
~Matrix() { }
|
||||
|
||||
/**
|
||||
* Opérateur de copie à partir d'une sous-matrice.
|
||||
*
|
||||
* Exemple : Matrix B = A.block(i,j,m,n);
|
||||
*/
|
||||
template<typename _OtherScalar, int OtherRows, int _OtherCols, int _OtherStorage>
|
||||
Matrix& operator= (const SubMatrix<_OtherScalar, OtherRows, _OtherCols, _OtherStorage>& submatrix)
|
||||
{
|
||||
// TODO copier les données de la sous-matrice.
|
||||
// Note : si les dimensions ne correspondent pas, la matrice doit être redimensionnée.
|
||||
// Vous pouvez présumer qu'il s'agit d'un stockage par colonnes.
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accesseur à une entrée de la matrice (lecture seule)
|
||||
*/
|
||||
_Scalar operator()(int i, int j) const
|
||||
{
|
||||
// TODO implementer
|
||||
return (double)(i + j);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accesseur à une entrée de la matrice (lecture ou écriture)
|
||||
*/
|
||||
_Scalar& operator()(int i, int j)
|
||||
{
|
||||
// TODO implementer
|
||||
// Indice : l'implémentation est identique à celle de la fonction précédente.
|
||||
_Scalar x = (double)(i + j);
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une sous-matrice pour un block de taille (rows, cols) à partir de l'index (i,j).
|
||||
*/
|
||||
SubMatrix<_Scalar, _RowsAtCompile, _ColsAtCompile, _StorageType> block(int i, int j, int rows, int cols) const
|
||||
{
|
||||
return SubMatrix<_Scalar, _RowsAtCompile, _ColsAtCompile, _StorageType>(*this, i, j, rows, cols);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule l'inverse de la matrice
|
||||
*/
|
||||
Matrix inverse() const
|
||||
{
|
||||
// Do nothing.
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la transposée de la matrice
|
||||
*/
|
||||
template<typename _OtherScalar, int _OtherRows, int _OtherCols, int _OtherStorage>
|
||||
Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage> transpose() const
|
||||
{
|
||||
// TODO calcule et retourne la transposée de la matrice.
|
||||
|
||||
return Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage>(); // pas bon, à changer
|
||||
}
|
||||
|
||||
/**
|
||||
* Affecte l'identité à la matrice
|
||||
*/
|
||||
inline void setIdentity()
|
||||
{
|
||||
// TODO affecter la valeur 0.0 partour, sauf sur la diagonale principale où c'est 1.0..
|
||||
// Votre implémentation devrait aussi fonctionner pour des matrices qui ne sont pas carrées.
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Classe Matrix spécialisée pour un stockage par lignes
|
||||
*/
|
||||
template <typename _Scalar, int _RowsAtCompile, int _ColsAtCompile>
|
||||
class Matrix< _Scalar, _RowsAtCompile, _ColsAtCompile, RowStorage> : public MatrixBase<_Scalar, _RowsAtCompile, _ColsAtCompile> {
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructeur par défaut
|
||||
*/
|
||||
Matrix() : MatrixBase<_Scalar, _RowsAtCompile, _ColsAtCompile>() { }
|
||||
|
||||
/**
|
||||
* Constructeur de copie
|
||||
*/
|
||||
Matrix(const Matrix& other) : MatrixBase<_Scalar, _RowsAtCompile, _ColsAtCompile>(other) { }
|
||||
|
||||
/**
|
||||
* Constructeur avec spécification du nombre de ligne et de colonnes
|
||||
*/
|
||||
explicit Matrix(int rows, int cols) : MatrixBase<_Scalar, _RowsAtCompile, _ColsAtCompile>(rows, cols) { }
|
||||
|
||||
/**
|
||||
* Destructeur
|
||||
*/
|
||||
~Matrix() { }
|
||||
|
||||
/**
|
||||
* Opérateur de copie à partir d'une sous-matrice.
|
||||
*
|
||||
* Exemple : Matrix B = A.block(i,j,m,n);
|
||||
*/
|
||||
template<typename _OtherScalar, int OtherRows, int _OtherCols, int _OtherStorage>
|
||||
Matrix& operator= (const SubMatrix<_OtherScalar, OtherRows, _OtherCols, _OtherStorage>& submatrix)
|
||||
{
|
||||
// TODO copier les données de la sous-matrice.
|
||||
// Note : si les dimensions ne correspondent pas, la matrice doit être redimensionnée.
|
||||
// Vous pouvez présumer qu'il s'agit d'un stockage par lignes.
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accesseur à une entrée de la matrice (lecture seule)
|
||||
*/
|
||||
_Scalar operator()(int i, int j) const
|
||||
{
|
||||
// TODO implementer
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accesseur à une entrée de la matrice (lecture ou écriture)
|
||||
*/
|
||||
_Scalar& operator()(int i, int j)
|
||||
{
|
||||
// TODO implementer
|
||||
_Scalar x = 0.0;
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une sous-matrice pour un block de taille (rows, cols) à partir de l'index (i,j).
|
||||
*/
|
||||
SubMatrix<_Scalar, _RowsAtCompile, _ColsAtCompile, RowStorage> block(int i, int j, int rows, int cols) const {
|
||||
return SubMatrix<_Scalar, _RowsAtCompile, _ColsAtCompile, RowStorage>(*this, i, j, rows, cols);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule l'inverse de la matrice
|
||||
*/
|
||||
Matrix inverse() const
|
||||
{
|
||||
// Do nothing.
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la transposée de la matrice
|
||||
*/
|
||||
Matrix<_Scalar, _ColsAtCompile, _RowsAtCompile, ColumnStorage> transpose() const
|
||||
{
|
||||
// TODO calcule et retourne la transposée de la matrice.
|
||||
// Optimisez cette fonction en tenant compte du type de stockage utilisé.
|
||||
|
||||
return Matrix<_Scalar, _ColsAtCompile, _RowsAtCompile, ColumnStorage>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Affecte l'identité à la matrice
|
||||
*/
|
||||
inline void setIdentity()
|
||||
{
|
||||
// TODO affecter la valeur 0.0 partour, sauf sur la diagonale principale où c'est 1.0..
|
||||
// Votre implémentation devrait aussi fonctionner pour des matrices qui ne sont pas carrées.
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Classe pour accéder à une sous-matrice.
|
||||
*
|
||||
* Un sous-matrice ne copie pas les données. Au lieu de cela, elle conserve une
|
||||
* référence à la matrice originale.
|
||||
*/
|
||||
template <typename _Scalar, int _RowsAtCompile, int _ColsAtCompile, int _StorageType>
|
||||
class SubMatrix
|
||||
{
|
||||
private:
|
||||
// Référence à la matrice originale
|
||||
Matrix<_Scalar, _RowsAtCompile, _ColsAtCompile, _StorageType>& m_matrix;
|
||||
|
||||
// Constructeur par défaut (privé)
|
||||
SubMatrix() {}
|
||||
|
||||
// (i,j) est le coin supérieur gauche de la sous-matrice
|
||||
int m_i; // Décalage en ligne
|
||||
int m_j; // Décalage en colonne
|
||||
|
||||
// la sous-matrice est de dimension : m_rows x m_cols
|
||||
int m_rows; // Hauteur de la sous-matrice (nombre de lignes)
|
||||
int m_cols; // Largeur de la sous-matrice (nombre de colonnes)
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructeur à partir d'une référence en lecture seule à une matrice.
|
||||
*/
|
||||
SubMatrix(const Matrix<_Scalar, _RowsAtCompile, _ColsAtCompile, _StorageType>& _matrix, int _i, int _j, int _rows, int _cols) :
|
||||
m_matrix(const_cast<Matrix<_Scalar, _RowsAtCompile, _ColsAtCompile, _StorageType>&>(_matrix)),
|
||||
m_i(_i), m_j(_j), m_rows(_rows), m_cols(_cols)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur à partir d'une référence en lecture et écriture à une matrice.
|
||||
*/
|
||||
explicit SubMatrix(Matrix<_Scalar, _RowsAtCompile, _ColsAtCompile, _StorageType>& _matrix, int _i, int _j, int _rows, int _cols) :
|
||||
m_matrix(_matrix),
|
||||
m_i(_i), m_j(_j), m_rows(_rows), m_cols(_cols)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur de copie
|
||||
*/
|
||||
SubMatrix(const SubMatrix& other) :
|
||||
m_matrix(other.m_matrix),
|
||||
m_i(other.m_i), m_j(other.m_j), m_rows(other.m_rows), m_cols(other.m_cols)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructeur
|
||||
*/
|
||||
~SubMatrix() { }
|
||||
|
||||
/**
|
||||
* Opérateur de copie (à partir d'une matrice)
|
||||
*
|
||||
* Copies toutes les entrées de la matrice dans la sous-matrice.
|
||||
*
|
||||
* Note : la taille de la matrice doit correspondre à la taille de la
|
||||
* sous-matrice.
|
||||
*/
|
||||
template<typename _OtherScalar, int _OtherRows, int _OtherCols, int _OtherStorage>
|
||||
SubMatrix& operator= (const Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage>& matrix)
|
||||
{
|
||||
// TODO Cpopie les valeurs de la matrice dans la sous-matrice.
|
||||
// Note les dimensions de la matrice doivent correspondre à celle de
|
||||
// la sous-matrice.
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accesseur aux entrées de la sous-matrice (lecture seule)
|
||||
*
|
||||
* Note : il faut s'assurer que les indices respectent la taille de la
|
||||
* sous-matrice
|
||||
*/
|
||||
_Scalar operator()(int i, int j) const
|
||||
{
|
||||
// TODO implémenter
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accesseur aux entrées de la sous-matrice (lecture et écriture)
|
||||
*
|
||||
* Note : il faut s'assurer que les indices respectent la taille de la
|
||||
* sous-matrice
|
||||
*/
|
||||
_Scalar& operator()(int i, int j)
|
||||
{
|
||||
// TODO implémenter
|
||||
_Scalar x = 0.0;
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la transposée de la sous-matrice sous la forme d'une matrice.
|
||||
*/
|
||||
template<typename _OtherScalar, int _OtherRows, int _OtherCols, int _OtherStorage>
|
||||
Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage> transpose() const
|
||||
{
|
||||
// TODO implémenter
|
||||
return Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage>();
|
||||
}
|
||||
|
||||
inline int rows() const { return m_rows; }
|
||||
inline int cols() const { return m_cols; }
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,357 @@
|
|||
#pragma once
|
||||
|
||||
/**
|
||||
* @file MatrixBase.h
|
||||
*
|
||||
* @brief Classe contenant les éléments de base des matrices et des vecteurs.
|
||||
*
|
||||
* Nom:
|
||||
* Code permanent :
|
||||
* Email :
|
||||
*
|
||||
*/
|
||||
|
||||
#include "DenseStorage.h"
|
||||
|
||||
namespace gti320
|
||||
{
|
||||
|
||||
/**
|
||||
* Classe de base pour les matrices et vecteurs à taille fixe.
|
||||
*/
|
||||
template <typename _Scalar, int _Rows, int _Cols>
|
||||
class MatrixBase
|
||||
{
|
||||
protected:
|
||||
DenseStorage<_Scalar, _Rows* _Cols> m_storage;
|
||||
|
||||
public:
|
||||
|
||||
typedef _Scalar Scalar;
|
||||
|
||||
/**
|
||||
* Constructeur par défaut
|
||||
*/
|
||||
MatrixBase() : m_storage() { }
|
||||
|
||||
/**
|
||||
* Constructeur de copie
|
||||
*/
|
||||
MatrixBase(const MatrixBase& other) : m_storage(other.m_storage) { }
|
||||
|
||||
explicit MatrixBase(int _rows, int _cols) : m_storage() { }
|
||||
|
||||
/**
|
||||
* Destructeur
|
||||
*/
|
||||
~MatrixBase() { }
|
||||
|
||||
|
||||
/**
|
||||
* Redimensionne la matrice
|
||||
*/
|
||||
void resize(int _rows, int _cols)
|
||||
{
|
||||
// Ne rien faire.
|
||||
}
|
||||
|
||||
/**
|
||||
* Opérateur de copie
|
||||
*/
|
||||
MatrixBase& operator=(const MatrixBase& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
m_storage = other.m_storage;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void setZero() { m_storage.setZero(); }
|
||||
static inline int cols() { return _Cols; }
|
||||
static inline int rows() { return _Rows; }
|
||||
|
||||
/**
|
||||
* Accès à la donnée membre de stockage (en lecture seule)
|
||||
*/
|
||||
const DenseStorage<_Scalar, _Rows* _Cols>& storage() const
|
||||
{
|
||||
return m_storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nombre d'éléments stockés dans le tampon.
|
||||
*/
|
||||
inline int size() const
|
||||
{
|
||||
return m_storage.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Accès au tampon de données ((lecture seule))
|
||||
*/
|
||||
const _Scalar* data() const
|
||||
{
|
||||
return m_storage.data();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Classe de base pour les matrices avec un nombre de lignes dynamique et un
|
||||
* nombre fixe de colonnes.
|
||||
*/
|
||||
template <typename _Scalar, int _Cols>
|
||||
class MatrixBase<_Scalar, Dynamic, _Cols>
|
||||
{
|
||||
protected:
|
||||
|
||||
DenseStorage<_Scalar, Dynamic> m_storage;
|
||||
int m_rows;
|
||||
|
||||
public:
|
||||
|
||||
typedef _Scalar Scalar;
|
||||
|
||||
/**
|
||||
* Constructeur par défaut
|
||||
*/
|
||||
MatrixBase() : m_storage(), m_rows(0) { }
|
||||
|
||||
explicit MatrixBase(int _rows, int _cols) : m_storage(_rows* _Cols), m_rows(_rows) { }
|
||||
|
||||
/**
|
||||
* Constructeur de copie
|
||||
*/
|
||||
MatrixBase(const MatrixBase& other) : m_storage(other.m_storage), m_rows(other.m_rows) { }
|
||||
|
||||
/**
|
||||
* Destructeur
|
||||
*/
|
||||
~MatrixBase() { }
|
||||
|
||||
/**
|
||||
* Opérateur de copie
|
||||
*/
|
||||
MatrixBase& operator=(const MatrixBase& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
m_storage = other.m_storage;
|
||||
m_rows = other.m_rows;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redimensionne la matrice
|
||||
*/
|
||||
void resize(int _rows, int _cols)
|
||||
{
|
||||
assert(_cols == _Cols);
|
||||
m_storage.resize(_rows * _Cols);
|
||||
m_rows = _rows;
|
||||
}
|
||||
|
||||
inline void setZero() { m_storage.setZero(); }
|
||||
|
||||
static inline int cols() { return _Cols; }
|
||||
inline int rows() const { return m_rows; }
|
||||
|
||||
/**
|
||||
* Accès à la donnée membre de stockage (en lecture seule)
|
||||
*/
|
||||
const DenseStorage<_Scalar, Dynamic>& storage() const
|
||||
{
|
||||
return m_storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nombre d'éléments stockés dans le tampon.
|
||||
*/
|
||||
inline int size() const
|
||||
{
|
||||
return m_storage.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Accès au tampon de données ((lecture seule))
|
||||
*/
|
||||
const _Scalar* data() const
|
||||
{
|
||||
return m_storage.data();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Classe de base pour les matrices avec un nombre fixe de lignes et un
|
||||
* nombre de colonnes dynamique.
|
||||
*/
|
||||
template <typename _Scalar, int _Rows>
|
||||
class MatrixBase<_Scalar, _Rows, Dynamic>
|
||||
{
|
||||
protected:
|
||||
|
||||
DenseStorage<_Scalar, Dynamic> m_storage;
|
||||
int m_cols;
|
||||
|
||||
public:
|
||||
|
||||
typedef _Scalar Scalar;
|
||||
|
||||
/**
|
||||
* Constructeur par défaut
|
||||
*/
|
||||
MatrixBase() : m_storage() { }
|
||||
|
||||
explicit MatrixBase(int _rows, int _cols) : m_storage(_rows* _cols), m_cols(_cols) { }
|
||||
|
||||
/**
|
||||
* Constructeur de copie
|
||||
*/
|
||||
MatrixBase(const MatrixBase& other) : m_storage(other.m_storage), m_cols(other.m_cols) { }
|
||||
|
||||
/**
|
||||
* Destructeur
|
||||
*/
|
||||
~MatrixBase() { }
|
||||
|
||||
/**
|
||||
* Opérateur de copie
|
||||
*/
|
||||
MatrixBase& operator=(const MatrixBase& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
m_storage = other.m_storage;
|
||||
m_cols = other.m_cols;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redimensionne la matrice
|
||||
*/
|
||||
void resize(int _rows, int _cols)
|
||||
{
|
||||
assert(_rows == _Rows);
|
||||
m_storage.resize(_Rows * _cols);
|
||||
m_cols = _cols;
|
||||
}
|
||||
|
||||
inline void setZero() { m_storage.setZero(); }
|
||||
|
||||
inline int cols() const { return m_cols; }
|
||||
static inline int rows() { return _Rows; }
|
||||
|
||||
/**
|
||||
* Accès à la donnée membre de stockage (en lecture seule)
|
||||
*/
|
||||
const DenseStorage<_Scalar, Dynamic>& storage() const
|
||||
{
|
||||
return m_storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nombre d'éléments stockés dans le tampon.
|
||||
*/
|
||||
inline int size() const
|
||||
{
|
||||
return m_storage.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Accès au tampon de données ((lecture seule))
|
||||
*/
|
||||
const _Scalar* data() const
|
||||
{
|
||||
return m_storage.data();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Classe de base pour les matrices avec un nombre de lignes et de colonnes
|
||||
* dynamiques.
|
||||
*/
|
||||
template <typename _Scalar>
|
||||
class MatrixBase<_Scalar, Dynamic, Dynamic>
|
||||
{
|
||||
protected:
|
||||
|
||||
DenseStorage<_Scalar, Dynamic> m_storage;
|
||||
int m_cols;
|
||||
int m_rows;
|
||||
|
||||
public:
|
||||
typedef _Scalar Scalar;
|
||||
|
||||
/**
|
||||
* Constructeur par défaut
|
||||
*/
|
||||
MatrixBase() : m_storage(), m_rows(0), m_cols(0) { }
|
||||
|
||||
explicit MatrixBase(int _rows, int _cols) : m_storage(_rows* _cols), m_rows(_rows), m_cols(_cols) { }
|
||||
|
||||
/**
|
||||
* Constructeur de copie
|
||||
*/
|
||||
MatrixBase(const MatrixBase& other) : m_storage(other.m_storage), m_rows(other.m_rows), m_cols(other.m_cols) { }
|
||||
|
||||
/**
|
||||
* Destructeur
|
||||
*/
|
||||
~MatrixBase() { }
|
||||
|
||||
/**
|
||||
* Opérateur de copie
|
||||
*/
|
||||
MatrixBase& operator=(const MatrixBase& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
resize(other.m_rows, other.m_cols);
|
||||
m_storage = other.m_storage;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redimensionne la matrice
|
||||
*/
|
||||
void resize(int _rows, int _cols)
|
||||
{
|
||||
m_storage.resize(_rows * _cols);
|
||||
m_rows = _rows;
|
||||
m_cols = _cols;
|
||||
}
|
||||
|
||||
inline void setZero() { m_storage.setZero(); }
|
||||
|
||||
inline int cols() const { return m_cols; }
|
||||
inline int rows() const { return m_rows; }
|
||||
|
||||
/**
|
||||
* Accès à la donnée membre de stockage (en lecture seule)
|
||||
*/
|
||||
const DenseStorage<_Scalar, Dynamic>& storage() const
|
||||
{
|
||||
return m_storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nombre d'éléments stockés dans le tampon.
|
||||
*/
|
||||
inline int size() const
|
||||
{
|
||||
return m_storage.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Accès au tampon de données ((lecture seule))
|
||||
*/
|
||||
const _Scalar* data() const
|
||||
{
|
||||
return m_storage.data();
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
#pragma once
|
||||
|
||||
/**
|
||||
* @file Operators.h
|
||||
*
|
||||
* @brief Opérateurs arithmétiques pour les matrices et les vecteurs.
|
||||
*
|
||||
* Nom:
|
||||
* Code permanent :
|
||||
* Email :
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Matrix.h"
|
||||
#include "Vector.h"
|
||||
|
||||
/**
|
||||
* Implémentation de divers opérateurs arithmétiques pour les matrices et les vecteurs.
|
||||
*/
|
||||
namespace gti320 {
|
||||
|
||||
/**
|
||||
* Multiplication : Matrice * Matrice (générique)
|
||||
*/
|
||||
template <typename _Scalar, int RowsA, int ColsA, int StorageA, int RowsB, int ColsB, int StorageB>
|
||||
Matrix<_Scalar, RowsA, ColsB> operator*(const Matrix<_Scalar, RowsA, ColsA, StorageA>& A, const Matrix<_Scalar, RowsB, ColsB, StorageB>& B)
|
||||
{
|
||||
// TODO implémenter
|
||||
return Matrix<_Scalar, RowsA, ColsB>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplication : Matrice (colonne) * Matrice (ligne)
|
||||
*
|
||||
* Spécialisation de l'opérateur de multiplication pour le cas où les matrices
|
||||
* ont un stockage à taille dynamique et où la matrice de gauche utilise un
|
||||
* stockage par colonnes et celle de droite un stockage par lignes.
|
||||
*/
|
||||
template <typename _Scalar>
|
||||
Matrix<_Scalar, Dynamic, Dynamic> operator*(const Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage>& A, const Matrix<_Scalar, Dynamic, Dynamic, RowStorage>& B)
|
||||
{
|
||||
// TODO : implémenter
|
||||
return Matrix<_Scalar, Dynamic, Dynamic>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplication : Matrice (ligne) * Matrice (colonne)
|
||||
*
|
||||
* Spécialisation de l'opérateur de multiplication pour le cas où les matrices
|
||||
* ont un stockage à taille dynamique et où la matrice de gauche utilise un
|
||||
* stockage par lignes et celle de droite un stockage par colonnes.
|
||||
*/
|
||||
template <typename _Scalar>
|
||||
Matrix<_Scalar, Dynamic, Dynamic> operator*(const Matrix<_Scalar, Dynamic, Dynamic, RowStorage>& A, const Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage>& B)
|
||||
{
|
||||
// TODO : implémenter
|
||||
return Matrix<_Scalar, Dynamic, Dynamic>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Addition : Matrice + Matrice (générique)
|
||||
*/
|
||||
template <typename _Scalar, int Rows, int Cols, int StorageA, int StorageB>
|
||||
Matrix<_Scalar, Rows, Cols> operator+(const Matrix<_Scalar, Rows, Cols, StorageA>& A, const Matrix<_Scalar, Rows, Cols, StorageB>& B)
|
||||
{
|
||||
// TODO : implémenter
|
||||
return Matrix<_Scalar, Rows, Cols>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Addition : Matrice (colonne) + Matrice (colonne)
|
||||
*
|
||||
* Spécialisation de l'opérateur d'addition pour le cas où les deux matrices
|
||||
* sont stockées par colonnes.
|
||||
*/
|
||||
template <typename _Scalar>
|
||||
Matrix<_Scalar, Dynamic, Dynamic> operator+(const Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage>& A, const Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage>& B)
|
||||
{
|
||||
// TODO : implémenter
|
||||
return Matrix<_Scalar, Dynamic, Dynamic>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Addition : Matrice (ligne) + Matrice (ligne)
|
||||
*
|
||||
* Spécialisation de l'opérateur d'addition pour le cas où les deux matrices
|
||||
* sont stockées par lignes.
|
||||
*/
|
||||
template <typename _Scalar>
|
||||
Matrix<_Scalar, Dynamic, Dynamic, RowStorage> operator+(const Matrix<_Scalar, Dynamic, Dynamic, RowStorage>& A, const Matrix<_Scalar, Dynamic, Dynamic, RowStorage>& B)
|
||||
{
|
||||
// TODO : implémenter
|
||||
return Matrix<_Scalar, Dynamic, Dynamic, RowStorage>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplication : Scalaire * Matrice (colonne)
|
||||
*
|
||||
* Spécialisation de l'opérateur de multiplication par un scalaire pour le
|
||||
* cas d'une matrice stockée par colonnes.
|
||||
*/
|
||||
template <typename _Scalar, int _Rows, int _Cols>
|
||||
Matrix<_Scalar, _Rows, _Cols, ColumnStorage> operator*(const _Scalar& a, const Matrix<_Scalar, _Rows, _Cols, ColumnStorage>& A)
|
||||
{
|
||||
// TODO : implémenter
|
||||
return Matrix<_Scalar, Dynamic, Dynamic>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplication : Scalaire * Matrice (ligne)
|
||||
*
|
||||
* Spécialisation de l'opérateur de multiplication par un scalaire pour le
|
||||
* cas d'une matrice stockée par lignes.
|
||||
*/
|
||||
template <typename _Scalar, int _Rows, int _Cols>
|
||||
Matrix<_Scalar, _Rows, _Cols, RowStorage> operator*(const _Scalar& a, const Matrix<_Scalar, _Rows, _Cols, RowStorage>& A)
|
||||
{
|
||||
// TODO : implémenter
|
||||
return Matrix<_Scalar, Dynamic, Dynamic, RowStorage>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplication : Matrice (ligne) * Vecteur
|
||||
*
|
||||
* Spécialisation de l'opérateur de multiplication matrice*vecteur pour le
|
||||
* cas où la matrice est représentée par lignes.
|
||||
*/
|
||||
template <typename _Scalar, int _Rows, int _Cols>
|
||||
Vector<_Scalar, _Rows> operator*(const Matrix<_Scalar, _Rows, _Cols, RowStorage>& A, const Vector<_Scalar, _Cols>& v)
|
||||
{
|
||||
// TODO : implémenter
|
||||
return Vector<_Scalar, _Rows>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplication : Matrice (colonne) * Vecteur
|
||||
*
|
||||
* Spécialisation de l'opérateur de multiplication matrice*vecteur pour le
|
||||
* cas où la matrice est représentée par colonnes.
|
||||
*/
|
||||
template <typename _Scalar, int _Rows, int _Cols>
|
||||
Vector<_Scalar, _Rows> operator*(const Matrix<_Scalar, _Rows, _Cols, ColumnStorage>& A, const Vector<_Scalar, _Cols>& v)
|
||||
{
|
||||
// TODO : implémenter
|
||||
return Vector<_Scalar, _Rows>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplication : Scalaire * Vecteur
|
||||
*/
|
||||
template <typename _Scalar, int _Rows>
|
||||
Vector<_Scalar, _Rows> operator*(const _Scalar& a, const Vector<_Scalar, _Rows>& v)
|
||||
{
|
||||
// TODO : implémenter
|
||||
return Vector<_Scalar, _Rows>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Addition : Vecteur + Vecteur
|
||||
*/
|
||||
template <typename _Scalar, int _RowsA, int _RowsB>
|
||||
Vector<_Scalar, _RowsA> operator+(const Vector<_Scalar, _RowsA>& a, const Vector<_Scalar, _RowsB>& b)
|
||||
{
|
||||
// TODO : implémenter
|
||||
return Vector<_Scalar, _RowsA>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Soustraction : Vecteur - Vecteur
|
||||
*/
|
||||
template <typename _Scalar, int _RowsA, int _RowsB>
|
||||
Vector<_Scalar, _RowsA> operator-(const Vector<_Scalar, _RowsA>& a, const Vector<_Scalar, _RowsB>& b)
|
||||
{
|
||||
// TODO : implémenter
|
||||
return Vector<_Scalar, _RowsA>();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
#pragma once
|
||||
|
||||
/**
|
||||
* @file Vector.h
|
||||
*
|
||||
* @brief Implémentation de vecteurs simples
|
||||
*
|
||||
* Nom:
|
||||
* Code permanent :
|
||||
* Email :
|
||||
*
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include "MatrixBase.h"
|
||||
|
||||
namespace gti320 {
|
||||
|
||||
/**
|
||||
* Classe vecteur générique.
|
||||
*
|
||||
* Cette classe réutilise la classe `MatrixBase` et ses spécialisations de
|
||||
* templates pour les manipulation bas niveau.
|
||||
*/
|
||||
template <typename _Scalar = double, int _Rows = Dynamic>
|
||||
class Vector : public MatrixBase<_Scalar, _Rows, 1> {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructeur par défaut
|
||||
*/
|
||||
Vector() : MatrixBase<_Scalar, _Rows, 1>() { }
|
||||
|
||||
/**
|
||||
* Contructeur à partir d'un taille (rows).
|
||||
*/
|
||||
explicit Vector(int rows) : MatrixBase<_Scalar, _Rows, 1>(rows, 1) { }
|
||||
|
||||
/**
|
||||
* Constructeur de copie
|
||||
*/
|
||||
Vector(const Vector& other) : MatrixBase<_Scalar, _Rows, 1>(other) { }
|
||||
|
||||
/**
|
||||
* Destructeur
|
||||
*/
|
||||
~Vector() { }
|
||||
|
||||
/**
|
||||
* Opérateur de copie
|
||||
*/
|
||||
Vector& operator=(const Vector& other)
|
||||
{
|
||||
// TODO implémenter
|
||||
this->m_storage = other.m_storage;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accesseur à une entrée du vecteur (lecture seule)
|
||||
*/
|
||||
_Scalar operator()(int i) const
|
||||
{
|
||||
// TODO implémenter
|
||||
return (double)i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accesseur à une entrée du vecteur (lecture et écriture)
|
||||
*/
|
||||
_Scalar& operator()(int i)
|
||||
{
|
||||
// TODO implémenter
|
||||
_Scalar x = (double)i;
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifie le nombre de lignes du vecteur
|
||||
*/
|
||||
void resize(int _rows)
|
||||
{
|
||||
MatrixBase<_Scalar, _Rows, 1>::resize(_rows, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produit scalaire de *this et other.
|
||||
*/
|
||||
inline _Scalar dot(const Vector& other) const
|
||||
{
|
||||
// TODO implémenter
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la norme euclidienne du vecteur
|
||||
*/
|
||||
inline _Scalar norm() const
|
||||
{
|
||||
// TODO implémenter
|
||||
return 0.0;
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,520 @@
|
|||
/**
|
||||
* @file main.cpp
|
||||
*
|
||||
* @brief Unit tests for a simple linear algebra library.
|
||||
*
|
||||
* Nom: William Nolin
|
||||
* Code permanent : NOLW76060101
|
||||
* Email : william.nolin.1@ens.etsmtl.ca
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Matrix.h"
|
||||
#include "Vector.h"
|
||||
#include "Math3D.h"
|
||||
#include "Operators.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <chrono>
|
||||
|
||||
using namespace gti320;
|
||||
|
||||
/**
|
||||
* Multiplication matrice * vecteur, utilisant une implémentation naive
|
||||
*/
|
||||
template<typename _Scalar>
|
||||
static inline Vector<_Scalar, Dynamic> naiveMatrixMult(const Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage>& A, const Vector<_Scalar, Dynamic>& v)
|
||||
{
|
||||
assert(A.cols() == v.rows());
|
||||
|
||||
Vector<_Scalar, Dynamic> b(A.rows());
|
||||
assert(b.rows() == A.rows());
|
||||
|
||||
for (int i = 0; i < A.rows(); ++i) {
|
||||
b(i) = 0.0;
|
||||
for (int j = 0; j < A.cols(); ++j) {
|
||||
b(i) += A(i, j) * v(j);
|
||||
}
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Addition matrice + matrice, utilisant une implémentation naive
|
||||
*/
|
||||
template<typename _Scalar>
|
||||
static inline Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage> naiveMatrixAddition(const Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage>& A, const Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage>& B)
|
||||
{
|
||||
assert(A.cols() == B.cols() && A.rows() == B.rows());
|
||||
|
||||
Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage> C(A.rows(), A.cols());
|
||||
assert(C.rows() == A.rows() && C.cols() == A.cols());
|
||||
for (int i = 0; i < C.rows(); ++i) {
|
||||
for (int j = 0; j < C.cols(); ++j) {
|
||||
C(i, j) = A(i, j) + B(i, j);
|
||||
}
|
||||
}
|
||||
return C;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplication matrice * matrice, utilisant une implémentation naive.
|
||||
*/
|
||||
template<typename _Scalar, int _Storage>
|
||||
static inline Matrix<_Scalar, Dynamic, Dynamic, _Storage> naiveMatrixMult(const Matrix<_Scalar, Dynamic, Dynamic, _Storage>& A, const Matrix<_Scalar, Dynamic, Dynamic, _Storage>& B)
|
||||
{
|
||||
assert(A.cols() == B.rows());
|
||||
Matrix<_Scalar, Dynamic, Dynamic> product(A.rows(), B.cols());
|
||||
for (int i = 0; i < A.rows(); ++i)
|
||||
{
|
||||
for (int j = 0; j < B.cols(); ++j)
|
||||
{
|
||||
for (int k = 0; k < A.cols(); ++k)
|
||||
{
|
||||
product(i, j) += A(i, k) * B(k, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
return product;
|
||||
}
|
||||
|
||||
// Test les matrice avec redimensionnement dynamique
|
||||
TEST(TestLabo1, DynamicMatrixTests)
|
||||
{
|
||||
// Crée une matrice à taille dynamique
|
||||
// (note : les valeurs par défaut du patron de la classe `Matrix` mettent le
|
||||
// le nombre de ligne et de colonnes à `Dynamic`)
|
||||
Matrix<double> M(3, 5);
|
||||
EXPECT_EQ(M.cols(), 5);
|
||||
EXPECT_EQ(M.rows(), 3);
|
||||
|
||||
// Redimensionne la matrice
|
||||
M.resize(100, 1000);
|
||||
EXPECT_EQ(M.cols(), 1000);
|
||||
EXPECT_EQ(M.rows(), 100);
|
||||
|
||||
// Test - stockage par colonnes
|
||||
Matrix<double, Dynamic, Dynamic, ColumnStorage> ColM(100, 100);
|
||||
ColM.setZero();
|
||||
ColM(0, 0) = 1.0;
|
||||
ColM(99, 99) = 99.0;
|
||||
ColM(10, 33) = 5.0;
|
||||
EXPECT_EQ(ColM(0, 0), 1.0);
|
||||
EXPECT_EQ(ColM(10, 33), 5.0);
|
||||
EXPECT_EQ(ColM(99, 99), 99.0);
|
||||
|
||||
// Test - stockage par lignes
|
||||
Matrix<double, Dynamic, Dynamic, RowStorage> RowM(5, 4);
|
||||
RowM.setZero();
|
||||
RowM(0, 0) = 2.1;
|
||||
RowM(3, 3) = -0.2;
|
||||
RowM(4, 3) = 1.2;
|
||||
EXPECT_EQ(RowM.rows(), 5);
|
||||
EXPECT_EQ(RowM.cols(), 4);
|
||||
EXPECT_DOUBLE_EQ(RowM(0, 0), 2.1);
|
||||
EXPECT_DOUBLE_EQ(RowM(3, 3), -0.2);
|
||||
EXPECT_DOUBLE_EQ(RowM(4, 3), 1.2);
|
||||
EXPECT_DOUBLE_EQ(RowM(3, 2), 0.0);
|
||||
|
||||
// Transposée
|
||||
const auto RowMT = RowM.transpose();
|
||||
EXPECT_EQ(RowMT.rows(), 4);
|
||||
EXPECT_EQ(RowMT.cols(), 5);
|
||||
EXPECT_DOUBLE_EQ(RowMT(0, 0), 2.1);
|
||||
EXPECT_DOUBLE_EQ(RowMT(3, 3), -0.2);
|
||||
EXPECT_DOUBLE_EQ(RowMT(3, 4), 1.2);
|
||||
EXPECT_DOUBLE_EQ(RowMT(2, 3), 0.0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Test pour les vecteurs à taille dynamique
|
||||
*/
|
||||
TEST(TestLabo1, DynamicVectorSizeTest)
|
||||
{
|
||||
Vector<double> v(5);
|
||||
v.setZero();
|
||||
|
||||
EXPECT_EQ(v.rows(), 5);
|
||||
|
||||
v.resize(3);
|
||||
EXPECT_EQ(v.rows(), 3);
|
||||
|
||||
v(0) = 1.0;
|
||||
v(1) = 2.0;
|
||||
v(2) = 3.0;
|
||||
|
||||
EXPECT_DOUBLE_EQ(v.norm(), 3.7416573867739413855837487323165);
|
||||
|
||||
Vector<double, Dynamic> v2(3);
|
||||
v2.setZero();
|
||||
v2(1) = 2.0;
|
||||
|
||||
EXPECT_DOUBLE_EQ(v2.dot(v), 4.0);
|
||||
EXPECT_DOUBLE_EQ(v2(0), 0.0);
|
||||
EXPECT_DOUBLE_EQ(v2(1), 2.0);
|
||||
EXPECT_DOUBLE_EQ(v2(2), 0.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test pour les matrice à taille fixe
|
||||
*/
|
||||
TEST(TestLabo1, Matrix4x4SizeTest)
|
||||
{
|
||||
Matrix4d M;
|
||||
M.setZero();
|
||||
|
||||
EXPECT_EQ(M.cols(), 4);
|
||||
EXPECT_EQ(M.rows(), 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test pour les opérateurs d'arithmétique matricielle.
|
||||
*/
|
||||
TEST(TestLabo1, MatrixMatrixOperators)
|
||||
{
|
||||
// Opérations arithmétiques avec matrices à taille dynamique
|
||||
{
|
||||
// Test : matrice identité
|
||||
Matrix<double> A(6, 6);
|
||||
A.setIdentity();
|
||||
EXPECT_DOUBLE_EQ(A(0, 0), 1.0);
|
||||
EXPECT_DOUBLE_EQ(A(1, 1), 1.0);
|
||||
EXPECT_DOUBLE_EQ(A(2, 2), 1.0);
|
||||
EXPECT_DOUBLE_EQ(A(3, 3), 1.0);
|
||||
EXPECT_DOUBLE_EQ(A(4, 4), 1.0);
|
||||
EXPECT_DOUBLE_EQ(A(5, 5), 1.0);
|
||||
EXPECT_DOUBLE_EQ(A(0, 1), 0.0);
|
||||
EXPECT_DOUBLE_EQ(A(1, 0), 0.0);
|
||||
|
||||
// Test : produit scalaire * matrice
|
||||
const double alpha = 2.5;
|
||||
Matrix<double> B = alpha * A;
|
||||
EXPECT_DOUBLE_EQ(B(0, 0), alpha);
|
||||
EXPECT_DOUBLE_EQ(B(1, 1), alpha);
|
||||
EXPECT_DOUBLE_EQ(B(2, 2), alpha);
|
||||
EXPECT_DOUBLE_EQ(B(3, 3), alpha);
|
||||
EXPECT_DOUBLE_EQ(B(4, 4), alpha);
|
||||
EXPECT_DOUBLE_EQ(B(5, 5), alpha);
|
||||
EXPECT_DOUBLE_EQ(B(0, 1), 0.0);
|
||||
EXPECT_DOUBLE_EQ(B(1, 0), 0.0);
|
||||
|
||||
// Test : produit matrice * matrice
|
||||
Matrix<double> C = A * B;
|
||||
EXPECT_DOUBLE_EQ(C(0, 0), A(0, 0) * B(0, 0));
|
||||
EXPECT_DOUBLE_EQ(C(1, 1), A(1, 1) * B(1, 1));
|
||||
EXPECT_DOUBLE_EQ(C(2, 2), A(2, 2) * B(2, 2));
|
||||
EXPECT_DOUBLE_EQ(C(3, 3), A(3, 3) * B(3, 3));
|
||||
EXPECT_DOUBLE_EQ(C(4, 4), A(4, 4) * B(4, 4));
|
||||
EXPECT_DOUBLE_EQ(C(5, 5), A(5, 5) * B(5, 5));
|
||||
EXPECT_DOUBLE_EQ(C(0, 1), 0.0);
|
||||
EXPECT_DOUBLE_EQ(C(2, 3), 0.0);
|
||||
|
||||
// Test : addition matrice * matrice
|
||||
Matrix<double> A_plus_B = A + B;
|
||||
EXPECT_DOUBLE_EQ(A_plus_B(0, 0), A(0, 0) + B(0, 0));
|
||||
EXPECT_DOUBLE_EQ(A_plus_B(1, 1), A(1, 1) + B(1, 1));
|
||||
EXPECT_DOUBLE_EQ(A_plus_B(2, 2), A(2, 2) + B(2, 2));
|
||||
EXPECT_DOUBLE_EQ(A_plus_B(3, 3), A(3, 3) + B(3, 3));
|
||||
EXPECT_DOUBLE_EQ(A_plus_B(4, 4), A(4, 4) + B(4, 4));
|
||||
EXPECT_DOUBLE_EQ(A_plus_B(5, 5), A(5, 5) + B(5, 5));
|
||||
EXPECT_DOUBLE_EQ(A_plus_B(0, 1), 0.0);
|
||||
EXPECT_DOUBLE_EQ(A_plus_B(2, 3), 0.0);
|
||||
}
|
||||
|
||||
// Opérations arithmétique avec matrices à stockage par lignes et par
|
||||
// colonnes.
|
||||
{
|
||||
// Création d'un matrice à stockage par lignes
|
||||
Matrix<double, Dynamic, Dynamic, RowStorage> A(5, 5);
|
||||
A(0, 0) = 0.8147; A(0, 1) = 0.0975; A(0, 2) = 0.1576; A(0, 3) = 0.1419; A(0, 4) = 0.6557;
|
||||
A(1, 0) = 0.9058; A(1, 1) = 0.2785; A(1, 2) = 0.9706; A(1, 3) = 0.4218; A(1, 4) = 0.0357;
|
||||
A(2, 0) = 0.1270; A(2, 1) = 0.5469; A(2, 2) = 0.9572; A(2, 3) = 0.9157; A(2, 4) = 0.8491;
|
||||
A(3, 0) = 0.9134; A(3, 1) = 0.9575; A(3, 2) = 0.4854; A(3, 3) = 0.7922; A(3, 4) = 0.9340;
|
||||
A(4, 0) = 0.6324; A(4, 1) = 0.9649; A(4, 2) = 0.8003; A(4, 3) = 0.9595; A(4, 4) = 0.6787;
|
||||
|
||||
// Test : transposée (le résultat est une matrice à stockage par
|
||||
// colonnes)
|
||||
Matrix<double, Dynamic, Dynamic, ColumnStorage> B = A.transpose();
|
||||
|
||||
// Test : multiplication matrix(ligne) * matrice(colonne)
|
||||
// Note : teste seulement la première et la dernière colonne
|
||||
const auto C = A * B;
|
||||
EXPECT_NEAR(C(0, 0), 1.14815820000000, 1e-3); EXPECT_NEAR(C(0, 4), 1.31659795000000, 1e-3);
|
||||
EXPECT_NEAR(C(1, 0), 1.00133748000000, 1e-3); EXPECT_NEAR(C(1, 4), 2.04727044000000, 1e-3);
|
||||
EXPECT_NEAR(C(2, 0), 0.99433707000000, 1e-3); EXPECT_NEAR(C(2, 4), 2.82896409000000, 1e-3);
|
||||
EXPECT_NEAR(C(3, 0), 1.63883925000000, 1e-3); EXPECT_NEAR(C(3, 4), 3.28401323000000, 1e-3);
|
||||
EXPECT_NEAR(C(4, 0), 1.31659795000000, 1e-3); EXPECT_NEAR(C(4, 4), 3.35271580000000, 1e-3);
|
||||
|
||||
|
||||
// Test : multiplication matrice(colonne) * matrice(ligne)
|
||||
// Note : teste seulement la première et la dernière colonne
|
||||
const auto C2 = B * A;
|
||||
EXPECT_NEAR(C2(0, 0), 2.73456805000000, 1e-3); EXPECT_NEAR(C2(0, 4), 1.95669703000000, 1e-3);
|
||||
EXPECT_NEAR(C2(1, 0), 1.88593811000000, 1e-3); EXPECT_NEAR(C2(1, 4), 2.08742862000000, 1e-3);
|
||||
EXPECT_NEAR(C2(2, 0), 2.07860468000000, 1e-3); EXPECT_NEAR(C2(2, 4), 1.94727447000000, 1e-3);
|
||||
EXPECT_NEAR(C2(3, 0), 1.94434955000000, 1e-3); EXPECT_NEAR(C2(3, 4), 2.27675041000000, 1e-3);
|
||||
EXPECT_NEAR(C2(4, 0), 1.95669703000000, 1e-3); EXPECT_NEAR(C2(4, 4), 2.48517748000000, 1e-3);
|
||||
|
||||
// Test : addition matrice(ligne) + matrice(ligne)
|
||||
// Note : teste seulement la première et la dernière colonne
|
||||
const auto A_plus_A = A + A;
|
||||
EXPECT_DOUBLE_EQ(A_plus_A(0, 0), A(0, 0) + A(0, 0)); EXPECT_DOUBLE_EQ(A_plus_A(0, 4), A(0, 4) + A(0, 4));
|
||||
EXPECT_DOUBLE_EQ(A_plus_A(1, 0), A(1, 0) + A(1, 0)); EXPECT_DOUBLE_EQ(A_plus_A(1, 4), A(1, 4) + A(1, 4));
|
||||
EXPECT_DOUBLE_EQ(A_plus_A(2, 0), A(2, 0) + A(2, 0)); EXPECT_DOUBLE_EQ(A_plus_A(2, 4), A(2, 4) + A(2, 4));
|
||||
EXPECT_DOUBLE_EQ(A_plus_A(3, 0), A(3, 0) + A(3, 0)); EXPECT_DOUBLE_EQ(A_plus_A(3, 4), A(3, 4) + A(3, 4));
|
||||
EXPECT_DOUBLE_EQ(A_plus_A(4, 0), A(4, 0) + A(4, 0)); EXPECT_DOUBLE_EQ(A_plus_A(4, 4), A(4, 4) + A(4, 4));
|
||||
|
||||
// Test : addition matrice(colonne) + matrice(colonne)
|
||||
// Note : teste seulement la première et la dernière colonne
|
||||
const auto B_plus_B = B + B;
|
||||
EXPECT_DOUBLE_EQ(B_plus_B(0, 0), B(0, 0) + B(0, 0)); EXPECT_DOUBLE_EQ(B_plus_B(0, 4), B(0, 4) + B(0, 4));
|
||||
EXPECT_DOUBLE_EQ(B_plus_B(1, 0), B(1, 0) + B(1, 0)); EXPECT_DOUBLE_EQ(B_plus_B(1, 4), B(1, 4) + B(1, 4));
|
||||
EXPECT_DOUBLE_EQ(B_plus_B(2, 0), B(2, 0) + B(2, 0)); EXPECT_DOUBLE_EQ(B_plus_B(2, 4), B(2, 4) + B(2, 4));
|
||||
EXPECT_DOUBLE_EQ(B_plus_B(3, 0), B(3, 0) + B(3, 0)); EXPECT_DOUBLE_EQ(B_plus_B(3, 4), B(3, 4) + B(3, 4));
|
||||
EXPECT_DOUBLE_EQ(B_plus_B(4, 0), B(4, 0) + B(4, 0)); EXPECT_DOUBLE_EQ(B_plus_B(4, 4), B(4, 4) + B(4, 4));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test pour la multiplication matrice * vecteur
|
||||
*/
|
||||
TEST(TestLabo1, MatrixVectorOperators)
|
||||
{
|
||||
// Vecteur à taille dynamique
|
||||
Vector<double> v(5);
|
||||
v(0) = 1.0;
|
||||
v(1) = 2.0;
|
||||
v(2) = 4.0;
|
||||
v(3) = 8.0;
|
||||
v(4) = 16.0;
|
||||
|
||||
// Test : multiplication par la matrice identité
|
||||
{
|
||||
Matrix<double> M(5, 5);
|
||||
M.setIdentity();
|
||||
|
||||
const auto b = M * v;
|
||||
EXPECT_DOUBLE_EQ(b(0), 1.0);
|
||||
EXPECT_DOUBLE_EQ(b(1), 2.0);
|
||||
EXPECT_DOUBLE_EQ(b(2), 4.0);
|
||||
EXPECT_DOUBLE_EQ(b(3), 8.0);
|
||||
EXPECT_DOUBLE_EQ(b(4), 16.0);
|
||||
}
|
||||
|
||||
// Test : multiplication par une matrice à taille dynamique avec stockage par ligne.
|
||||
{
|
||||
Matrix<double, Dynamic, Dynamic, RowStorage> M(5, 5);
|
||||
M.setIdentity();
|
||||
M = 2.0 * M;
|
||||
|
||||
Vector<double> b2 = M * v;
|
||||
EXPECT_DOUBLE_EQ(b2(0), 2.0);
|
||||
EXPECT_DOUBLE_EQ(b2(1), 4.0);
|
||||
EXPECT_DOUBLE_EQ(b2(2), 8.0);
|
||||
EXPECT_DOUBLE_EQ(b2(3), 16.0);
|
||||
EXPECT_DOUBLE_EQ(b2(4), 32.0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opérateurs d'arithmétique vectorielle
|
||||
*/
|
||||
TEST(TestLabo1, VectorOperators)
|
||||
{
|
||||
Vector<double> v(5);
|
||||
v(0) = 0.1;
|
||||
v(1) = 0.2;
|
||||
v(2) = 0.4;
|
||||
v(3) = 0.8;
|
||||
v(4) = 1.6;
|
||||
|
||||
// Test : multiplication scalaire * vecteur
|
||||
const double alpha = 4.0;
|
||||
const auto v2 = alpha * v;
|
||||
EXPECT_DOUBLE_EQ(v2(0), alpha * v(0));
|
||||
EXPECT_DOUBLE_EQ(v2(1), alpha * v(1));
|
||||
EXPECT_DOUBLE_EQ(v2(2), alpha * v(2));
|
||||
EXPECT_DOUBLE_EQ(v2(3), alpha * v(3));
|
||||
EXPECT_DOUBLE_EQ(v2(4), alpha * v(4));
|
||||
|
||||
// Test : addition vecteur + vecteur
|
||||
const auto v3 = v + v2;
|
||||
EXPECT_DOUBLE_EQ(v3(0), v(0) + v2(0));
|
||||
EXPECT_DOUBLE_EQ(v3(1), v(1) + v2(1));
|
||||
EXPECT_DOUBLE_EQ(v3(2), v(2) + v2(2));
|
||||
EXPECT_DOUBLE_EQ(v3(3), v(3) + v2(3));
|
||||
EXPECT_DOUBLE_EQ(v3(4), v(4) + v2(4));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mathématiques 3D
|
||||
*/
|
||||
TEST(TestLabo1, Math3D)
|
||||
{
|
||||
// Test : norme d'un vecteur de dimension 3
|
||||
Vector3d v;
|
||||
v.setZero();
|
||||
v(1) = 2.0;
|
||||
EXPECT_EQ(v.rows(), 3);
|
||||
EXPECT_EQ(v.cols(), 1);
|
||||
EXPECT_DOUBLE_EQ(v(0), 0.0);
|
||||
EXPECT_DOUBLE_EQ(v(1), 2.0);
|
||||
EXPECT_DOUBLE_EQ(v(2), 0.0);
|
||||
EXPECT_DOUBLE_EQ(v.norm(), 2.0);
|
||||
|
||||
// Test : calcul de la norme d'un deuxième vecteur 3D
|
||||
Vector3d v2;
|
||||
v2(0) = 4.0;
|
||||
v2(1) = 2.0;
|
||||
v2(2) = 5.0;
|
||||
EXPECT_EQ(v2.rows(), 3);
|
||||
EXPECT_EQ(v2.cols(), 1);
|
||||
EXPECT_DOUBLE_EQ(v2(0), 4.0);
|
||||
EXPECT_DOUBLE_EQ(v2(1), 2.0);
|
||||
EXPECT_DOUBLE_EQ(v2(2), 5.0);
|
||||
EXPECT_DOUBLE_EQ(v2.norm(), 6.7082039324993690892275210061938);
|
||||
|
||||
// Test : produit scalaire
|
||||
EXPECT_DOUBLE_EQ(v.dot(v2), 4.0);
|
||||
|
||||
// Test : matrice identité 4x4
|
||||
Matrix4d M;
|
||||
M.setIdentity();
|
||||
EXPECT_DOUBLE_EQ(M(0, 0), 1.0);
|
||||
EXPECT_DOUBLE_EQ(M(0, 1), 0.0);
|
||||
EXPECT_DOUBLE_EQ(M(0, 2), 0.0);
|
||||
EXPECT_DOUBLE_EQ(M(1, 1), 1.0);
|
||||
EXPECT_DOUBLE_EQ(M(1, 0), 0.0);
|
||||
EXPECT_DOUBLE_EQ(M(1, 2), 0.0);
|
||||
EXPECT_DOUBLE_EQ(M(2, 0), 0.0);
|
||||
EXPECT_DOUBLE_EQ(M(2, 1), 0.0);
|
||||
EXPECT_DOUBLE_EQ(M(2, 2), 1.0);
|
||||
|
||||
// Test : création d'une matrice de rotation de 45 degrés autour de l'axe des x
|
||||
const auto Rx = makeRotation<double>(M_PI / 4.0, 0, 0);
|
||||
EXPECT_NEAR(Rx(0, 0), 1, 1e-3); EXPECT_NEAR(Rx(0, 1), 0, 1e-3); EXPECT_NEAR(Rx(0, 2), 0, 1e-3);
|
||||
EXPECT_NEAR(Rx(1, 0), 0, 1e-3); EXPECT_NEAR(Rx(1, 1), 0.7071, 1e-3); EXPECT_NEAR(Rx(1, 2), -0.7071, 1e-3);
|
||||
EXPECT_NEAR(Rx(2, 0), 0, 1e-3); EXPECT_NEAR(Rx(2, 1), 0.7071, 1e-3); EXPECT_NEAR(Rx(2, 2), 0.7071, 1e-3);
|
||||
|
||||
// Test : création d'une matrice de rotation de 45 degrés autour de l'axe des y
|
||||
const auto Ry = makeRotation<double>(0, M_PI / 4.0, 0);
|
||||
EXPECT_NEAR(Ry(0, 0), 0.7071, 1e-3); EXPECT_NEAR(Ry(0, 1), 0, 1e-3); EXPECT_NEAR(Ry(0, 2), 0.7071, 1e-3);
|
||||
EXPECT_NEAR(Ry(1, 0), 0, 1e-3); EXPECT_NEAR(Ry(1, 1), 1, 1e-3); EXPECT_NEAR(Ry(1, 2), 0, 1e-3);
|
||||
EXPECT_NEAR(Ry(2, 0), -0.7071, 1e-3); EXPECT_NEAR(Ry(2, 1), 0, 1e-3); EXPECT_NEAR(Ry(2, 2), 0.7071, 1e-3);
|
||||
|
||||
// Test : création d'une matrice de rotation de 45 degrés autour de l'axe des z
|
||||
const auto Rz = makeRotation<double>(0, 0, M_PI / 4.0);
|
||||
EXPECT_NEAR(Rz(0, 0), 0.7071, 1e-3); EXPECT_NEAR(Rz(0, 1), -0.7071, 1e-3); EXPECT_NEAR(Rz(0, 2), 0, 1e-3);
|
||||
EXPECT_NEAR(Rz(1, 0), 0.7071, 1e-3); EXPECT_NEAR(Rz(1, 1), 0.7071, 1e-3); EXPECT_NEAR(Rz(1, 2), 0, 1e-3);
|
||||
EXPECT_NEAR(Rz(2, 0), 0, 1e-3); EXPECT_NEAR(Rz(2, 1), 0, 1e-3); EXPECT_NEAR(Rz(2, 2), 1, 1e-3);
|
||||
|
||||
// Test : création d'une matrice de rotation quelconque.
|
||||
const auto Rxyz = makeRotation<double>(M_PI / 3.0, -M_PI / 6.0, M_PI / 4.0);
|
||||
EXPECT_NEAR(Rxyz(0, 0), 0.6124, 1e-3); EXPECT_NEAR(Rxyz(0, 1), -0.6597, 1e-3); EXPECT_NEAR(Rxyz(0, 2), 0.4356, 1e-3);
|
||||
EXPECT_NEAR(Rxyz(1, 0), 0.6124, 1e-3); EXPECT_NEAR(Rxyz(1, 1), 0.0474, 1e-3); EXPECT_NEAR(Rxyz(1, 2), -0.7891, 1e-3);
|
||||
EXPECT_NEAR(Rxyz(2, 0), 0.5, 1e-3); EXPECT_NEAR(Rxyz(2, 1), 0.75, 1e-3); EXPECT_NEAR(Rxyz(2, 2), 0.4330, 1e-3);
|
||||
|
||||
// Test : création d'une transformation homogène via la sous-matrice 3x3 en
|
||||
// utilisant la fonction `block`
|
||||
M.block(0, 0, 3, 3) = Rxyz;
|
||||
M(0, 3) = -0.1;
|
||||
M(1, 3) = 1.0;
|
||||
M(2, 3) = 2.1;
|
||||
|
||||
// Test : calcule l'inverse de la matrice M et vérifie que M^(-1) * M * v = v
|
||||
const Matrix4d Minv = M.inverse();
|
||||
const Vector3d v3 = Minv * (M * v2);
|
||||
EXPECT_DOUBLE_EQ(v3(0), v2(0));
|
||||
EXPECT_DOUBLE_EQ(v3(1), v2(1));
|
||||
EXPECT_DOUBLE_EQ(v3(2), v2(2));
|
||||
|
||||
// Test : translation d'un vecteur 3D effectuée avec une matrice 4x4 en coordonnées homogènes
|
||||
Matrix4d T;
|
||||
T.setIdentity();
|
||||
T(0, 3) = 1.2;
|
||||
T(1, 3) = 2.5;
|
||||
T(2, 3) = -4.0;
|
||||
const Vector3d t = T * v3;
|
||||
EXPECT_DOUBLE_EQ(t(0), v3(0) + 1.2);
|
||||
EXPECT_DOUBLE_EQ(t(1), v3(1) + 2.5);
|
||||
EXPECT_DOUBLE_EQ(t(2), v3(2) - 4.0);
|
||||
|
||||
// Test : inverse d'un matrice de rotation
|
||||
const Matrix3d Rinv = Rxyz.inverse();
|
||||
const Matrix3d RT = Rxyz.transpose<double, 3, 3, ColumnStorage>();
|
||||
EXPECT_DOUBLE_EQ(Rinv(0, 0), RT(0, 0));
|
||||
EXPECT_DOUBLE_EQ(Rinv(1, 1), RT(1, 1));
|
||||
EXPECT_DOUBLE_EQ(Rinv(0, 2), RT(0, 2));
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test des performance de la multiplication matrice * vecteur
|
||||
* pour de grandes dimensions.
|
||||
*/
|
||||
TEST(TestLabo1, PerformanceMatrixVector)
|
||||
{
|
||||
Matrix<double> A(16384, 16384); // grande matrice avec stockage colonne
|
||||
Vector<double> v(16384); // grand vecteur
|
||||
|
||||
using namespace std::chrono;
|
||||
// Test : multiplication avec l'algorithme naif.
|
||||
high_resolution_clock::time_point t = high_resolution_clock::now();
|
||||
naiveMatrixMult(A, v);
|
||||
const duration<double> naive_t = duration_cast<duration<double>>(high_resolution_clock::now() - t);
|
||||
|
||||
// Test : multiplication avec l'implémentation spécifique pour les matrices avec
|
||||
// stockage par colonnes.
|
||||
t = high_resolution_clock::now();
|
||||
A* v;
|
||||
const duration<double> optimal_t = duration_cast<duration<double>>(high_resolution_clock::now() - t);
|
||||
|
||||
EXPECT_TRUE(optimal_t < 0.4 * naive_t)
|
||||
<< "Naive time: " << duration_cast<std::chrono::milliseconds>(naive_t).count() << " ms, "
|
||||
<< "optimized time: " << duration_cast<std::chrono::milliseconds>(optimal_t).count() << " ms";
|
||||
}
|
||||
|
||||
/**
|
||||
* Test des performances de l'addition matrice + matrice
|
||||
* pour de grandes dimensions.
|
||||
*/
|
||||
TEST(TestLabo1, PerformanceLargeMatrixMatrix)
|
||||
{
|
||||
// deux grandes matrices à stockage par colonnes
|
||||
Matrix<double> A(16384, 16384);
|
||||
Matrix<double> B(16384, 16384);
|
||||
|
||||
using namespace std::chrono;
|
||||
high_resolution_clock::time_point t = high_resolution_clock::now();
|
||||
// Test : addition avec l'algorithme naif
|
||||
naiveMatrixAddition(A, B);
|
||||
const duration<double> naive_t = duration_cast<duration<double>>(high_resolution_clock::now() - t);
|
||||
|
||||
// Test : addition avec l'implémentation spécifique pour les matrices à
|
||||
// stockage par colonnes.
|
||||
t = high_resolution_clock::now();
|
||||
A + B;
|
||||
const duration<double> optimal_t = duration_cast<duration<double>>(high_resolution_clock::now() - t);
|
||||
|
||||
EXPECT_TRUE(optimal_t < 0.4 * naive_t);
|
||||
}
|
||||
|
||||
TEST(TestLabo1, Supplementaires)
|
||||
{
|
||||
// TODO remplacez le code avec vos propres tests ici
|
||||
EXPECT_TRUE(false);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
const int ret = RUN_ALL_TESTS();
|
||||
|
||||
return ret;
|
||||
}
|
Loading…
Reference in New Issue