<commit_before>﻿#pragma once

#include "physics/inertia_tensor.hpp"

#include "geometry/barycentre_calculator.hpp"
#include "geometry/identity.hpp"
#include "geometry/point.hpp"
#include "geometry/rotation.hpp"
#include "inertia_tensor.hpp"

namespace principia {
namespace physics {
namespace internal_inertia_tensor {

using geometry::Barycentre;
using geometry::Bivector;
using geometry::Commutator;
using geometry::Identity;
using geometry::Rotation;
using geometry::SymmetricProduct;

template<typename Frame>
InertiaTensor<Frame>::InertiaTensor(
    Mass const& mass,
    R3x3Matrix<MomentOfInertia> const& coordinates,
    Position<Frame> const& centre_of_mass)
    : InertiaTensor(mass,
                    MakeSymmetricBilinearForm(coordinates),
                    centre_of_mass) {}

template<typename Frame>
Mass const& InertiaTensor<Frame>::mass() const {
  return mass_;
}

template<typename Frame>
Position<Frame> const& InertiaTensor<Frame>::centre_of_mass() const {
  return centre_of_mass_;
}

template<typename Frame>
template<typename ToFrame>
InertiaTensor<ToFrame> InertiaTensor<Frame>::Transform(
    RigidTransformation<Frame, ToFrame> const& transformation) const {
  Displacement<ToFrame> const displacement =
      ToFrame::origin - transformation(Frame::origin);
  SymmetricBilinearForm<MomentOfInertia, ToFrame> const transformed_form =
      transformation.linear_map()(form_) +
      mass_ * SymmetricProduct(displacement, displacement);
  Position<ToFrame> const transformed_centre_of_mass =
      transformation(centre_of_mass_);
  return InertiaTensor<ToFrame>(mass_,
                                transformed_form,
                                transformed_centre_of_mass);
}

template<typename Frame>
template<typename PrincipalAxesFrame>
typename InertiaTensor<Frame>::template PrincipalAxes<PrincipalAxesFrame>
InertiaTensor<Frame>::Diagonalize() const {
  struct IntermediateFrame {};

  auto const eigensystem = form_.Diagonalize<IntermediateFrame>();

  // The eigenvalues are {Σx², Σy², Σz²} in increasing order.
  R3x3Matrix<MomentOfInertia> const eigensystem_form_coordinates =
      eigensystem.form.coordinates();

  // The moment of inertia in increasing order are
  // {Σ(x² + y²), Σ(x² + z²), Σ(y² + z²)}, which does *not* correspond to the
  // ordered eigenvalues of the "classical" inertia tensor, which are
  // {Σ(y² + z²), Σ(x² + z²), Σ(x² + y²)}.  We address this by multiplying the
  // rotation by another one that swaps x and z.
  R3Element<MomentOfInertia> const moments_of_inertia(
      eigensystem_form_coordinates(0, 0) + eigensystem_form_coordinates(1, 1),
      eigensystem_form_coordinates(2, 2) + eigensystem_form_coordinates(0, 0),
      eigensystem_form_coordinates(1, 1) + eigensystem_form_coordinates(2, 2));

  auto const y = Bivector<double, IntermediateFrame>({0, 1, 0});
  auto const z = Bivector<double, IntermediateFrame>({0, 0, 1});
  Rotation<IntermediateFrame, PrincipalAxesFrame> const swap_x_and_z(
      z, y, Commutator(z, y));<commit_msg>Fix a Linux compilation error.<commit_after>﻿#pragma once

#include "physics/inertia_tensor.hpp"

#include "geometry/barycentre_calculator.hpp"
#include "geometry/identity.hpp"
#include "geometry/point.hpp"
#include "geometry/rotation.hpp"
#include "inertia_tensor.hpp"

namespace principia {
namespace physics {
namespace internal_inertia_tensor {

using geometry::Barycentre;
using geometry::Bivector;
using geometry::Commutator;
using geometry::Identity;
using geometry::Rotation;
using geometry::SymmetricProduct;

template<typename Frame>
InertiaTensor<Frame>::InertiaTensor(
    Mass const& mass,
    R3x3Matrix<MomentOfInertia> const& coordinates,
    Position<Frame> const& centre_of_mass)
    : InertiaTensor(mass,
                    MakeSymmetricBilinearForm(coordinates),
                    centre_of_mass) {}

template<typename Frame>
Mass const& InertiaTensor<Frame>::mass() const {
  return mass_;
}

template<typename Frame>
Position<Frame> const& InertiaTensor<Frame>::centre_of_mass() const {
  return centre_of_mass_;
}

template<typename Frame>
template<typename ToFrame>
InertiaTensor<ToFrame> InertiaTensor<Frame>::Transform(
    RigidTransformation<Frame, ToFrame> const& transformation) const {
  Displacement<ToFrame> const displacement =
      ToFrame::origin - transformation(Frame::origin);
  SymmetricBilinearForm<MomentOfInertia, ToFrame> const transformed_form =
      transformation.linear_map()(form_) +
      mass_ * SymmetricProduct(displacement, displacement);
  Position<ToFrame> const transformed_centre_of_mass =
      transformation(centre_of_mass_);
  return InertiaTensor<ToFrame>(mass_,
                                transformed_form,
                                transformed_centre_of_mass);
}

template<typename Frame>
template<typename PrincipalAxesFrame>
typename InertiaTensor<Frame>::template PrincipalAxes<PrincipalAxesFrame>
InertiaTensor<Frame>::Diagonalize() const {
  struct IntermediateFrame {};

  auto const eigensystem = form_.template Diagonalize<IntermediateFrame>();

  // The eigenvalues are {Σx², Σy², Σz²} in increasing order.
  R3x3Matrix<MomentOfInertia> const eigensystem_form_coordinates =
      eigensystem.form.coordinates();

  // The moment of inertia in increasing order are
  // {Σ(x² + y²), Σ(x² + z²), Σ(y² + z²)}, which does *not* correspond to the
  // ordered eigenvalues of the "classical" inertia tensor, which are
  // {Σ(y² + z²), Σ(x² + z²), Σ(x² + y²)}.  We address this by multiplying the
  // rotation by another one that swaps x and z.
  R3Element<MomentOfInertia> const moments_of_inertia(
      eigensystem_form_coordinates(0, 0) + eigensystem_form_coordinates(1, 1),
      eigensystem_form_coordinates(2, 2) + eigensystem_form_coordinates(0, 0),
      eigensystem_form_coordinates(1, 1) + eigensystem_form_coordinates(2, 2));

  auto const y = Bivector<double, IntermediateFrame>({0, 1, 0});
  auto const z = Bivector<double, IntermediateFrame>({0, 0, 1});
  Rotation<IntermediateFrame, PrincipalAxesFrame> const swap_x_and_z(
      z, y, Commutator(z, y));
{'fraction_non_alphanumeric': 0.10243341006247944, 'fraction_numerical': 0.007563301545544229, 'mean_word_length': 4.946236559139785, 'pattern_counts': {'":': 0, '<': 61, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2990915', 'n_tokens_mistral': 1992, 'n_tokens_neox': 1889, 'n_words': 424}