<commit_before>//
//  For more information, please see: http://software.sci.utah.edu
//
//  The MIT License
//
//  Copyright (c) 2009 Scientific Computing and Imaging Institute,
//  University of Utah.
//
//
//  Permission is hereby granted, free of charge, to any person obtaining a
//  copy of this software and associated documentation files (the "Software"),
//  to deal in the Software without restriction, including without limitation
//  the rights to use, copy, modify, merge, publish, distribute, sublicense,
//  and/or sell copies of the Software, and to permit persons to whom the
//  Software is furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included
//  in all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
//  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
//  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
//  DEALINGS IN THE SOFTWARE.
//

#include <Core/Datatypes/Matrix.h>
#include <Core/Datatypes/Field.h>
#include <Core/Datatypes/Mesh.h>

#include <Core/Parser/ArrayMathInterpreter.h>
#include <Core/Parser/ArrayMathFunctionCatalog.h>

namespace ArrayMathFunctions {

//--------------------------------------------------------------------------
// Source functions

// Field data to buffer
bool center_fn(SCIRun::ArrayMathProgramCode& pc)
{
  // Get where the data needs to be stored
  double* data0 = pc.get_variable(0);
  // Get the field where the data is coming from
  SCIRun::VMesh* data1 = pc.get_vmesh(1);

  double* data0_end = data0 + pc.get_size();
  SCIRun::VMesh::Node::index_type idx = 3*pc.get_index();

  // Safety check
  if (idx+pc.get_size() > data1->num_nodes()) return (false);

  while(data0 != data0_end)
  {
    SCIRun::Point p;
    data1->get_center(p,idx); idx++;
    *data0 = p.x(); data0++;
    *data0 = p.y(); data0++;
    *data0 = p.z(); data0++;
  }

  return (true);
}

bool center_fe(SCIRun::ArrayMathProgramCode& pc)
{
  // Get where the data needs to be stored
  double* data0 = pc.get_variable(0);
  // Get the field where the data is coming from
  SCIRun::VMesh* data1 = pc.get_vmesh(1);

  double* data0_end = data0 + pc.get_size();
  SCIRun::VMesh::Elem::index_type idx = 3*pc.get_index();

  // Safety check
  if (idx+pc.get_size() > data1->num_elems()) return (false);

  while(data0 != data0_end)
  {
    SCIRun::Point p;
    data1->get_center(p,idx); idx++;
    *data0 = p.x(); data0++;
    *data0 = p.y(); data0++;
    *data0 = p.z(); data0++;
  }

  return (true);
}

bool size_fn(SCIRun::ArrayMathProgramCode& pc)
{
  // Get where the data needs to be stored
  double* data0 = pc.get_variable(0);
  // Get the field where the data is coming from
  SCIRun::VMesh* data1 = pc.get_vmesh(1);

  double* data0_end = data0 + pc.get_size();
  SCIRun::VMesh::Node::index_type idx = pc.get_index();

  // Safety check
  if (idx+pc.get_size() > data1->num_nodes()) return (false);

  while(data0 != data0_end)
  {
    *data0 = data1->get_size(idx); idx++; data0++;
  }

  return (true);
}

bool size_fe(SCIRun::ArrayMathProgramCode& pc)
{
  // Get where the data needs to be stored
  double* data0 = pc.get_variable(0);
  // Get the field where the data is coming from
  SCIRun::VMesh* data1 = pc.get_vmesh(1);

  double* data0_end = data0 + pc.get_size();
  SCIRun::VMesh::Elem::index_type idx = pc.get_index();

  // Safety check
  if (idx+pc.get_size() > data1->num_elems()) return (false);

  while(data0 != data0_end)
  {
    *data0 = data1->get_size(idx); idx++; data0++;
  }

  return (true);
}

bool normal_fn(SCIRun::ArrayMathProgramCode& pc)
{
  // Get where the data needs to be stored
  double* data0 = pc.get_variable(0);
  // Get the field where the data is coming from
  SCIRun::VMesh* data1 = pc.get_vmesh(1);
  data1->synchronize(SCIRun::Mesh::NORMALS_E);

  double* data0_end = data0 + 3*pc.get_size();
  SCIRun::VMesh::Node::index_type idx = pc.get_index();

  // Safety check
  if (idx+pc.get_size() > data1->num_nodes()) return (false);

  while(data0 != data0_end)
  {
    SCIRun::Vector v;
    data1->get_normal(v,idx); idx++;
    *data0 = v.x(); data0++;
    *data0 = v.y(); data0++;
    *data0 = v.z(); data0++;
  }

  return (true);
}

bool normal_fe(SCIRun::ArrayMathProgramCode& pc)
{
  // Get where the data needs to be stored
  double* data0 = pc.get_variable(0);
  // Get the field where the data is coming from
  SCIRun::VMesh* data1 = pc.get_vmesh(1);
  data1->synchronize(SCIRun::Mesh::NORMALS_E);

  double* data0_end = data0 + 3*pc.get_size();
  SCIRun::VMesh::Elem::index_type idx = pc.get_index();

  // Safety check
  if (idx+pc.get_size() > data1->num_elems()) return (false);
  SCIRun::VMesh::coords_type coords;
  data1->get_element_center(coords);

  while(data0 != data0_end)
  {
    SCIRun::Vector v;
    data1->get_normal(v,coords,idx); idx++;
    *data0 = v.x(); data0++;
    *data0 = v.y(); data0++;
    *data0 = v.z(); data0++;
  }

  return (true);
}

bool dimension_fn(SCIRun::ArrayMathProgramCode& pc)
{
  // Get where the data needs to be stored
  double* data0 = pc.get_variable(0);
  // Get the field where the data is coming from
  SCIRun::VMesh* data1 = pc.get_vmesh(1);

  double* data0_end = data0 + pc.get_size();
  SCIRun::VMesh::Node::index_type idx = pc.get_index();

  // Safety check
  if (idx+pc.get_size() > data1->num_nodes()) return (false);

  while(data0 != data0_end)
  {
    *data0 = 0.0; data0++;
  }

  return (true);
}

bool dimension_fe(SCIRun::ArrayMathProgramCode& pc)
{
  // Get where the data needs to be stored
  double* data0 = pc.get_variable(0);
  // Get the field where the data is coming from
  SCIRun::VMesh* data1 = pc.get_vmesh(1);

  double* data0_end = data0 + pc.get_size();
  SCIRun::VMesh::Elem::index_type idx = pc.get_index();

  double val = static_cast<double>(data1->dimensionality());
  while(data0 != data0_end)
  {
    *data0 = val; data0++;
  }

  return (true);
}

} //end namespace

namespace SCIRun {

void
InsertElementArrayMathFunctionCatalog(ArrayMathFunctionCatalogHandle& catalog)
{
  // Source functions
  catalog->add_function(ArrayMathFunctions::center_fn,"center$FN","V");
  catalog->add_function(ArrayMathFunctions::center_fe,"center$FE","V");

  catalog->add_function(ArrayMathFunctions::size_fn,"size$FN","S");
  catalog->add_function(ArrayMathFunctions::size_fe,"size$FE","S");
  catalog->add_function(ArrayMathFunctions::size_fn,"length$FN","S");
  catalog->add_function(ArrayMathFunctions::size_fe,"length$FE","S");
  catalog->add_function(ArrayMathFunctions::size_fn,"area$FN","S");
  catalog->add_function(ArrayMathFunctions::size_fe,"area$FE","S");
  catalog->add_function(ArrayMathFunctions::size_fn,"volume$FN","S");
  catalog->add_function(ArrayMathFunctions::size_fe,"volume$FE","S");

  catalog->add_function(ArrayMathFunctions::normal_fn,"normal$FN","V");
  catalog->add_function(ArrayMathFunctions::normal_fe,"normal$FE","V");

  catalog->add_function(ArrayMathFunctions::dimension_fn,"dimension$FN","S");
  catalog->add_function(ArrayMathFunctions::dimension_fe,"dimension$FE","S");

}

} // end namespace
<commit_msg>ArrayMath<commit_after>//
//  For more information, please see: http://software.sci.utah.edu
//
//  The MIT License
//
//  Copyright (c) 2009 Scientific Computing and Imaging Institute,
//  University of Utah.
//
//
//  Permission is hereby granted, free of charge, to any person obtaining a
//  copy of this software and associated documentation files (the "Software"),
//  to deal in the Software without restriction, including without limitation
//  the rights to use, copy, modify, merge, publish, distribute, sublicense,
//  and/or sell copies of the Software, and to permit persons to whom the
//  Software is furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included
//  in all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
//  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
//  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
//  DEALINGS IN THE SOFTWARE.
//

#include <Core/Datatypes/Matrix.h>
#include <Core/Datatypes/Legacy/Field/Field.h>
#include <Core/Datatypes/Legacy/Field/Mesh.h>
#include <Core/Datatypes/Legacy/Field/VMesh.h>
#include <Core/Datatypes/Legacy/Field/VField.h>

#include <Core/Parser/ArrayMathInterpreter.h>
#include <Core/Parser/ArrayMathFunctionCatalog.h>

using namespace SCIRun;
using namespace SCIRun::Core::Geometry;

namespace ArrayMathFunctions {

//--------------------------------------------------------------------------
// Source functions

// Field data to buffer
bool center_fn(SCIRun::ArrayMathProgramCode& pc)
{
  // Get where the data needs to be stored
  double* data0 = pc.get_variable(0);
  // Get the field where the data is coming from
  SCIRun::VMesh* data1 = pc.get_vmesh(1);

  double* data0_end = data0 + pc.get_size();
  SCIRun::VMesh::Node::index_type idx = 3*pc.get_index();

  // Safety check
  if (idx+pc.get_size() > data1->num_nodes()) return (false);

  while(data0 != data0_end)
  {
    Point p;
    data1->get_center(p,idx); idx++;
    *data0 = p.x(); data0++;
    *data0 = p.y(); data0++;
    *data0 = p.z(); data0++;
  }

  return (true);
}

bool center_fe(SCIRun::ArrayMathProgramCode& pc)
{
  // Get where the data needs to be stored
  double* data0 = pc.get_variable(0);
  // Get the field where the data is coming from
  SCIRun::VMesh* data1 = pc.get_vmesh(1);

  double* data0_end = data0 + pc.get_size();
  SCIRun::VMesh::Elem::index_type idx = 3*pc.get_index();

  // Safety check
  if (idx+pc.get_size() > data1->num_elems()) return (false);

  while(data0 != data0_end)
  {
    Point p;
    data1->get_center(p,idx); idx++;
    *data0 = p.x(); data0++;
    *data0 = p.y(); data0++;
    *data0 = p.z(); data0++;
  }

  return (true);
}

bool size_fn(SCIRun::ArrayMathProgramCode& pc)
{
  // Get where the data needs to be stored
  double* data0 = pc.get_variable(0);
  // Get the field where the data is coming from
  SCIRun::VMesh* data1 = pc.get_vmesh(1);

  double* data0_end = data0 + pc.get_size();
  SCIRun::VMesh::Node::index_type idx = pc.get_index();

  // Safety check
  if (idx+pc.get_size() > data1->num_nodes()) return (false);

  while(data0 != data0_end)
  {
    *data0 = data1->get_size(idx); idx++; data0++;
  }

  return (true);
}

bool size_fe(SCIRun::ArrayMathProgramCode& pc)
{
  // Get where the data needs to be stored
  double* data0 = pc.get_variable(0);
  // Get the field where the data is coming from
  SCIRun::VMesh* data1 = pc.get_vmesh(1);

  double* data0_end = data0 + pc.get_size();
  SCIRun::VMesh::Elem::index_type idx = pc.get_index();

  // Safety check
  if (idx+pc.get_size() > data1->num_elems()) return (false);

  while(data0 != data0_end)
  {
    *data0 = data1->get_size(idx); idx++; data0++;
  }

  return (true);
}

bool normal_fn(SCIRun::ArrayMathProgramCode& pc)
{
  // Get where the data needs to be stored
  double* data0 = pc.get_variable(0);
  // Get the field where the data is coming from
  SCIRun::VMesh* data1 = pc.get_vmesh(1);
  data1->synchronize(SCIRun::Mesh::NORMALS_E);

  double* data0_end = data0 + 3*pc.get_size();
  SCIRun::VMesh::Node::index_type idx = pc.get_index();

  // Safety check
  if (idx+pc.get_size() > data1->num_nodes()) return (false);

  while(data0 != data0_end)
  {
    Vector v;
    data1->get_normal(v,idx); idx++;
    *data0 = v.x(); data0++;
    *data0 = v.y(); data0++;
    *data0 = v.z(); data0++;
  }

  return (true);
}

bool normal_fe(SCIRun::ArrayMathProgramCode& pc)
{
  // Get where the data needs to be stored
  double* data0 = pc.get_variable(0);
  // Get the field where the data is coming from
  SCIRun::VMesh* data1 = pc.get_vmesh(1);
  data1->synchronize(SCIRun::Mesh::NORMALS_E);

  double* data0_end = data0 + 3*pc.get_size();
  SCIRun::VMesh::Elem::index_type idx = pc.get_index();

  // Safety check
  if (idx+pc.get_size() > data1->num_elems()) return (false);
  SCIRun::VMesh::coords_type coords;
  data1->get_element_center(coords);

  while(data0 != data0_end)
  {
    Vector v;
    data1->get_normal(v,coords,idx); idx++;
    *data0 = v.x(); data0++;
    *data0 = v.y(); data0++;
    *data0 = v.z(); data0++;
  }

  return (true);
}

bool dimension_fn(SCIRun::ArrayMathProgramCode& pc)
{
  // Get where the data needs to be stored
  double* data0 = pc.get_variable(0);
  // Get the field where the data is coming from
  SCIRun::VMesh* data1 = pc.get_vmesh(1);

  double* data0_end = data0 + pc.get_size();
  SCIRun::VMesh::Node::index_type idx = pc.get_index();

  // Safety check
  if (idx+pc.get_size() > data1->num_nodes()) return (false);

  while(data0 != data0_end)
  {
    *data0 = 0.0; data0++;
  }

  return (true);
}

bool dimension_fe(SCIRun::ArrayMathProgramCode& pc)
{
  // Get where the data needs to be stored
  double* data0 = pc.get_variable(0);
  // Get the field where the data is coming from
  SCIRun::VMesh* data1 = pc.get_vmesh(1);

  double* data0_end = data0 + pc.get_size();
  SCIRun::VMesh::Elem::index_type idx = pc.get_index();

  double val = static_cast<double>(data1->dimensionality());
  while(data0 != data0_end)
  {
    *data0 = val; data0++;
  }

  return (true);
}

} //end namespace

namespace SCIRun {

void
InsertElementArrayMathFunctionCatalog(ArrayMathFunctionCatalogHandle& catalog)
{
  // Source functions
  catalog->add_function(ArrayMathFunctions::center_fn,"center$FN","V");
  catalog->add_function(ArrayMathFunctions::center_fe,"center$FE","V");

  catalog->add_function(ArrayMathFunctions::size_fn,"size$FN","S");
  catalog->add_function(ArrayMathFunctions::size_fe,"size$FE","S");
  catalog->add_function(ArrayMathFunctions::size_fn,"length$FN","S");
  catalog->add_function(ArrayMathFunctions::size_fe,"length$FE","S");
  catalog->add_function(ArrayMathFunctions::size_fn,"area$FN","S");
  catalog->add_function(ArrayMathFunctions::size_fe,"area$FE","S");
  catalog->add_function(ArrayMathFunctions::size_fn,"volume$FN","S");
  catalog->add_function(ArrayMathFunctions::size_fe,"volume$FE","S");

  catalog->add_function(ArrayMathFunctions::normal_fn,"normal$FN","V");
  catalog->add_function(ArrayMathFunctions::normal_fe,"normal$FE","V");

  catalog->add_function(ArrayMathFunctions::dimension_fn,"dimension$FN","S");
  catalog->add_function(ArrayMathFunctions::dimension_fe,"dimension$FE","S");

}

} // end namespace
<|endoftext|>


<commit_before>template <typename T>
inline void Density::add_k_point_contribution_dm(K_point* kp__, mdarray<double_complex, 4>& density_matrix__)
{
    PROFILE("sirius::Density::add_k_point_contribution_dm");

    if (ctx_.full_potential()) {
        /* non-magnetic or spin-collinear case */
        if (ctx_.num_mag_dims() != 3) {
            for (int ispn = 0; ispn < ctx_.num_spins(); ispn++) {
                int nbnd = kp__->num_occupied_bands(ispn);

                mdarray<double_complex, 2> wf1(unit_cell_.max_mt_basis_size(), nbnd);
                mdarray<double_complex, 2> wf2(unit_cell_.max_mt_basis_size(), nbnd);

                for (int ialoc = 0; ialoc < kp__->spinor_wave_functions(ispn).spl_num_atoms().local_size(); ialoc++) {
                    int ia            = kp__->spinor_wave_functions(ispn).spl_num_atoms()[ialoc];
                    int mt_basis_size = unit_cell_.atom(ia).type().mt_basis_size();
                    int offset_wf     = kp__->spinor_wave_functions(ispn).offset_mt_coeffs(ialoc);

                    for (int i = 0; i < nbnd; i++) {
                        for (int xi = 0; xi < mt_basis_size; xi++) {
                            auto c = kp__->spinor_wave_functions(ispn).mt_coeffs().prime(offset_wf + xi, i);
                            wf1(xi, i) = std::conj(c);
                            wf2(xi, i) = c * kp__->band_occupancy(i + ispn * ctx_.num_fv_states()) * kp__->weight();
                        }
                    }
                    /* add |psi_j> n_j <psi_j| to density matrix */
                    linalg<CPU>::gemm(0, 1, mt_basis_size, mt_basis_size, nbnd, linalg_const<double_complex>::one(),
                                      &wf1(0, 0), wf1.ld(), &wf2(0, 0), wf2.ld(), linalg_const<double_complex>::one(),
                                      density_matrix__.at<CPU>(0, 0, ispn, ia), density_matrix__.ld());
                }
            }
        } else {
            int nbnd = kp__->num_occupied_bands();

            mdarray<double_complex, 3> wf1(unit_cell_.max_mt_basis_size(), nbnd, ctx_.num_spins());
            mdarray<double_complex, 3> wf2(unit_cell_.max_mt_basis_size(), nbnd, ctx_.num_spins());

            assert(kp__->spinor_wave_functions(0).spl_num_atoms().local_size() ==
                   kp__->spinor_wave_functions(1).spl_num_atoms().local_size());

            for (int ialoc = 0; ialoc < kp__->spinor_wave_functions(0).spl_num_atoms().local_size(); ialoc++) {
                int ia            = kp__->spinor_wave_functions(0).spl_num_atoms()[ialoc];
                int mt_basis_size = unit_cell_.atom(ia).type().mt_basis_size();
                int offset_wf     = kp__->spinor_wave_functions(0).offset_mt_coeffs(ialoc);

                for (int ispn = 0; ispn < ctx_.num_spins(); ispn++) {
                    for (int i = 0; i < nbnd; i++) {

                        for (int xi = 0; xi < mt_basis_size; xi++) {
                            auto c = kp__->spinor_wave_functions(ispn).mt_coeffs().prime(offset_wf + xi, i);
                            wf1(xi, i, ispn) = std::conj(c);
                            wf2(xi, i, ispn) = c * kp__->band_occupancy(i) * kp__->weight();
                        }
                    }
                }
                /* compute diagonal terms */
                for (int ispn = 0; ispn < 2; ispn++) {
                    linalg<CPU>::gemm(0, 1, mt_basis_size, mt_basis_size, nbnd, linalg_const<double_complex>::one(),
                                      &wf1(0, 0, ispn), wf1.ld(), &wf2(0, 0, ispn), wf2.ld(),
                                      linalg_const<double_complex>::one(), density_matrix__.at<CPU>(0, 0, ispn, ia),
                                      density_matrix__.ld());
                }
                /* offdiagonal term */
                linalg<CPU>::gemm(0, 1, mt_basis_size, mt_basis_size, nbnd, linalg_const<double_complex>::one(),
                                  &wf1(0, 0, 1), wf1.ld(), &wf2(0, 0, 0), wf2.ld(), linalg_const<double_complex>::one(),
                                  density_matrix__.at<CPU>(0, 0, 2, ia), density_matrix__.ld());
            }
        }
    } else { /* pseudopotential */
        if (!ctx_.unit_cell().mt_lo_basis_size()) {
            return;
        }

        kp__->beta_projectors().prepare();
        auto& bp_chunks = ctx_.beta_projector_chunks();

        if (ctx_.num_mag_dims() != 3) {
            for (int chunk = 0; chunk < bp_chunks.num_chunks(); chunk++) {
                kp__->beta_projectors().generate(chunk);

                for (int ispn = 0; ispn < ctx_.num_spins(); ispn++) {
                    /* total number of occupied bands for this spin */
                    int nbnd = kp__->num_occupied_bands(ispn);
                    /* compute <beta|psi> */
                    auto beta_psi = kp__->beta_projectors().inner<T>(chunk, kp__->spinor_wave_functions(ispn), 0, nbnd);

                    /* number of beta projectors */
                    int nbeta = bp_chunks(chunk).num_beta_;

                    splindex<block> spl_nbnd(nbnd, kp__->comm().size(), kp__->comm().rank());

                    int nbnd_loc = spl_nbnd.local_size();
                    if (nbnd_loc) { // TODO: this part can also be moved to GPU
                     #pragma omp parallel
                        {
                            /* auxiliary arrays */
                            mdarray<double_complex, 2> bp1(nbeta, nbnd_loc);
                            mdarray<double_complex, 2> bp2(nbeta, nbnd_loc);
                            #pragma omp for
                            for (int ia = 0; ia < bp_chunks(chunk).num_atoms_; ia++) {
                                int nbf  = bp_chunks(chunk).desc_(beta_desc_idx::nbf, ia);
                                int offs = bp_chunks(chunk).desc_(beta_desc_idx::offset, ia);
                                int ja   = bp_chunks(chunk).desc_(beta_desc_idx::ia, ia);

                                for (int i = 0; i < nbnd_loc; i++) {
                                    int j = spl_nbnd[i];

                                    for (int xi = 0; xi < nbf; xi++) {
                                        bp1(xi, i) = beta_psi(offs + xi, j);
                                        bp2(xi, i) = std::conj(bp1(xi, i)) * kp__->weight() *
                                                     kp__->band_occupancy(j + ispn * ctx_.num_fv_states());
                                    }
                                }

                                linalg<CPU>::gemm(0, 1, nbf, nbf, nbnd_loc, linalg_const<double_complex>::one(),
                                                  &bp1(0, 0), bp1.ld(), &bp2(0, 0), bp2.ld(),
                                                  linalg_const<double_complex>::one(),
                                                  &density_matrix__(0, 0, ispn, ja),

                                                  density_matrix__.ld());
                            }
                        }
                    }
                }
            }
        } else {
            for (int chunk = 0; chunk < bp_chunks.num_chunks(); chunk++) {
                kp__->beta_projectors().generate(chunk);

                /* number of beta projectors */
                int nbeta = bp_chunks(chunk).num_beta_;

                /* total number of occupied bands */
                int nbnd = kp__->num_occupied_bands();

                splindex<block> spl_nbnd(nbnd, kp__->comm().size(), kp__->comm().rank());
                int nbnd_loc = spl_nbnd.local_size();

                /* auxiliary arrays */
                mdarray<double_complex, 3> bp1(nbeta, nbnd_loc, 2);
                mdarray<double_complex, 3> bp2(nbeta, nbnd_loc, 2);

                for (int ispn = 0; ispn < ctx_.num_spins(); ispn++) {
                    /* compute <beta|psi> */
                    auto beta_psi = kp__->beta_projectors().inner<T>(chunk, kp__->spinor_wave_functions(ispn), 0, nbnd);
                    #pragma omp parallel for schedule(static)
                    for (int i = 0; i < nbnd_loc; i++) {
                        int j = spl_nbnd[i];

                        for (int m = 0; m < nbeta; m++) {
                            bp1(m, i, ispn) = beta_psi(m, j);
                            bp2(m, i, ispn) = std::conj(beta_psi(m, j)) * kp__->weight() * kp__->band_occupancy(j);
                        }
                    }
                }
                for (int ia = 0; ia < bp_chunks(chunk).num_atoms_; ia++) {
                    int nbf  = bp_chunks(chunk).desc_(beta_desc_idx::nbf, ia);
                    int offs = bp_chunks(chunk).desc_(beta_desc_idx::offset, ia);
                    int ja   = bp_chunks(chunk).desc_(beta_desc_idx::ia, ia);
                    if (ctx_.unit_cell().atom(ja).type().pp_desc().spin_orbit_coupling) {
                        mdarray<double_complex, 3> bp3(nbf, nbnd_loc, 2);
                        bp3.zero();
                        /* We already have the <beta|psi> but we need to rotate
                         *  them when the spin orbit interaction is included in the
                         *  pseudo potential.
                         *
                         *  We rotate \f[\langle\beta|\psi\rangle\f] accordingly by multiplying it with
                         *  the \f[f^{\sigma\sigma^{'}}_{\xi,\xi^'}\f]
                         */

                        for (int xi1 = 0; xi1 < nbf; xi1++) {
                            for (int i = 0; i < nbnd_loc; i++) {
                                int j = spl_nbnd[i];
                                for (int xi1p = 0; xi1p < nbf; xi1p++) {
                                    if (ctx_.unit_cell().atom(ja).type().compare_index_beta_functions(xi1, xi1p)) {
                                        bp3(xi1, i, 0) +=
                                            bp1(offs + xi1p, i, 0) *
                                                ctx_.unit_cell().atom(ja).type().f_coefficients(xi1, xi1p, 0, 0) +
                                            bp1(offs + xi1p, i, 1) *
                                                ctx_.unit_cell().atom(ja).type().f_coefficients(xi1, xi1p, 0, 1);
                                        bp3(xi1, i, 1) +=
                                            bp1(offs + xi1p, i, 0) *
                                                ctx_.unit_cell().atom(ja).type().f_coefficients(xi1, xi1p, 1, 0) +
                                            bp1(offs + xi1p, i, 1) *
                                                ctx_.unit_cell().atom(ja).type().f_coefficients(xi1, xi1p, 1, 1);
                                    }
                                }
                            }
                        }

                        for (int xi1 = 0; xi1 < nbf; xi1++) {
                            for (int i = 0; i < nbnd_loc; i++) {
                                bp1(offs + xi1, i, 0) = bp3(xi1, i, 0);
                                bp1(offs + xi1, i, 1) = bp3(xi1, i, 1);
                            }
                        }

                        bp3.zero();

                        for (int xi1 = 0; xi1 < nbf; xi1++) {
                            for (int i = 0; i < nbnd_loc; i++) {
                                for (int xi1p = 0; xi1p < nbf; xi1p++) {
                                    if (ctx_.unit_cell().atom(ja).type().compare_index_beta_functions(xi1, xi1p)) {
                                        bp3(xi1, i, 0) +=
                                            bp2(offs + xi1p, i, 0) *
                                                ctx_.unit_cell().atom(ja).type().f_coefficients(xi1p, xi1, 0, 0) +
                                            bp2(offs + xi1p, i, 1) *
                                                ctx_.unit_cell().atom(ja).type().f_coefficients(xi1p, xi1, 1, 0);
                                        bp3(xi1, i, 1) +=
                                            bp2(offs + xi1p, i, 0) *
                                                ctx_.unit_cell().atom(ja).type().f_coefficients(xi1p, xi1, 0, 1) +
                                            bp2(offs + xi1p, i, 1) *
                                                ctx_.unit_cell().atom(ja).type().f_coefficients(xi1p, xi1, 1, 1);
                                    }
                                }
                            }
                        }

                        for (int xi1 = 0; xi1 < nbf; xi1++) {
                            for (int i = 0; i < nbnd_loc; i++) {
                                bp2(offs + xi1, i, 0) = bp3(xi1, i, 0);
                                bp2(offs + xi1, i, 1) = bp3(xi1, i, 1);
                            }
                        }
                    }
                }

                if (nbnd_loc) {
                    #pragma omp parallel for
                    for (int ia = 0; ia < bp_chunks(chunk).num_atoms_; ia++) {
                        int nbf  = bp_chunks(chunk).desc_(beta_desc_idx::nbf, ia);
                        int offs = bp_chunks(chunk).desc_(beta_desc_idx::offset, ia);
                        int ja   = bp_chunks(chunk).desc_(beta_desc_idx::ia, ia);
                        /* compute diagonal spin blocks */
                        for (int ispn = 0; ispn < 2; ispn++) {
                            linalg<CPU>::gemm(0, 1, nbf, nbf, nbnd_loc, linalg_const<double_complex>::one(),
                                              &bp1(offs, 0, ispn), bp1.ld(), &bp2(offs, 0, ispn), bp2.ld(),
                                              linalg_const<double_complex>::one(), &density_matrix__(0, 0, ispn, ja),
                                              density_matrix__.ld());
                        }
                        /* off-diagonal spin block */
                        linalg<CPU>::gemm(0, 1, nbf, nbf, nbnd_loc, linalg_const<double_complex>::one(),
                                          &bp1(offs, 0, 0), bp1.ld(), &bp2(offs, 0, 1), bp2.ld(),
                                          linalg_const<double_complex>::one(), &density_matrix__(0, 0, 2, ja),
                                          density_matrix__.ld());
                    }
                }
            }
        }
        kp__->beta_projectors().dismiss();
    }
}
<commit_msg>minor fix in formatting<commit_after>template <typename T>
inline void Density::add_k_point_contribution_dm(K_point* kp__, mdarray<double_complex, 4>& density_matrix__)
{
    PROFILE("sirius::Density::add_k_point_contribution_dm");

    if (ctx_.full_potential()) {
        /* non-magnetic or spin-collinear case */
        if (ctx_.num_mag_dims() != 3) {
            for (int ispn = 0; ispn < ctx_.num_spins(); ispn++) {
                int nbnd = kp__->num_occupied_bands(ispn);

                mdarray<double_complex, 2> wf1(unit_cell_.max_mt_basis_size(), nbnd);
                mdarray<double_complex, 2> wf2(unit_cell_.max_mt_basis_size(), nbnd);

                for (int ialoc = 0; ialoc < kp__->spinor_wave_functions(ispn).spl_num_atoms().local_size(); ialoc++) {
                    int ia            = kp__->spinor_wave_functions(ispn).spl_num_atoms()[ialoc];
                    int mt_basis_size = unit_cell_.atom(ia).type().mt_basis_size();
                    int offset_wf     = kp__->spinor_wave_functions(ispn).offset_mt_coeffs(ialoc);

                    for (int i = 0; i < nbnd; i++) {
                        for (int xi = 0; xi < mt_basis_size; xi++) {
                            auto c = kp__->spinor_wave_functions(ispn).mt_coeffs().prime(offset_wf + xi, i);
                            wf1(xi, i) = std::conj(c);
                            wf2(xi, i) = c * kp__->band_occupancy(i + ispn * ctx_.num_fv_states()) * kp__->weight();
                        }
                    }
                    /* add |psi_j> n_j <psi_j| to density matrix */
                    linalg<CPU>::gemm(0, 1, mt_basis_size, mt_basis_size, nbnd, linalg_const<double_complex>::one(),
                                      &wf1(0, 0), wf1.ld(), &wf2(0, 0), wf2.ld(), linalg_const<double_complex>::one(),
                                      density_matrix__.at<CPU>(0, 0, ispn, ia), density_matrix__.ld());
                }
            }
        } else {
            int nbnd = kp__->num_occupied_bands();

            mdarray<double_complex, 3> wf1(unit_cell_.max_mt_basis_size(), nbnd, ctx_.num_spins());
            mdarray<double_complex, 3> wf2(unit_cell_.max_mt_basis_size(), nbnd, ctx_.num_spins());

            assert(kp__->spinor_wave_functions(0).spl_num_atoms().local_size() ==
                   kp__->spinor_wave_functions(1).spl_num_atoms().local_size());

            for (int ialoc = 0; ialoc < kp__->spinor_wave_functions(0).spl_num_atoms().local_size(); ialoc++) {
                int ia            = kp__->spinor_wave_functions(0).spl_num_atoms()[ialoc];
                int mt_basis_size = unit_cell_.atom(ia).type().mt_basis_size();
                int offset_wf     = kp__->spinor_wave_functions(0).offset_mt_coeffs(ialoc);

                for (int ispn = 0; ispn < ctx_.num_spins(); ispn++) {
                    for (int i = 0; i < nbnd; i++) {

                        for (int xi = 0; xi < mt_basis_size; xi++) {
                            auto c = kp__->spinor_wave_functions(ispn).mt_coeffs().prime(offset_wf + xi, i);
                            wf1(xi, i, ispn) = std::conj(c);
                            wf2(xi, i, ispn) = c * kp__->band_occupancy(i) * kp__->weight();
                        }
                    }
                }
                /* compute diagonal terms */
                for (int ispn = 0; ispn < 2; ispn++) {
                    linalg<CPU>::gemm(0, 1, mt_basis_size, mt_basis_size, nbnd, linalg_const<double_complex>::one(),
                                      &wf1(0, 0, ispn), wf1.ld(), &wf2(0, 0, ispn), wf2.ld(),
                                      linalg_const<double_complex>::one(), density_matrix__.at<CPU>(0, 0, ispn, ia),
                                      density_matrix__.ld());
                }
                /* offdiagonal term */
                linalg<CPU>::gemm(0, 1, mt_basis_size, mt_basis_size, nbnd, linalg_const<double_complex>::one(),
                                  &wf1(0, 0, 1), wf1.ld(), &wf2(0, 0, 0), wf2.ld(), linalg_const<double_complex>::one(),
                                  density_matrix__.at<CPU>(0, 0, 2, ia), density_matrix__.ld());
            }
        }
    } else { /* pseudopotential */
        if (!ctx_.unit_cell().mt_lo_basis_size()) {
            return;
        }

        kp__->beta_projectors().prepare();
        auto& bp_chunks = ctx_.beta_projector_chunks();

        if (ctx_.num_mag_dims() != 3) {
            for (int chunk = 0; chunk < bp_chunks.num_chunks(); chunk++) {
                kp__->beta_projectors().generate(chunk);

                for (int ispn = 0; ispn < ctx_.num_spins(); ispn++) {
                    /* total number of occupied bands for this spin */
                    int nbnd = kp__->num_occupied_bands(ispn);
                    /* compute <beta|psi> */
                    auto beta_psi = kp__->beta_projectors().inner<T>(chunk, kp__->spinor_wave_functions(ispn), 0, nbnd);

                    /* number of beta projectors */
                    int nbeta = bp_chunks(chunk).num_beta_;

                    splindex<block> spl_nbnd(nbnd, kp__->comm().size(), kp__->comm().rank());

                    int nbnd_loc = spl_nbnd.local_size();
                    if (nbnd_loc) { // TODO: this part can also be moved to GPU
                     #pragma omp parallel
                        {
                            /* auxiliary arrays */
                            mdarray<double_complex, 2> bp1(nbeta, nbnd_loc);
                            mdarray<double_complex, 2> bp2(nbeta, nbnd_loc);
                            #pragma omp for
                            for (int ia = 0; ia < bp_chunks(chunk).num_atoms_; ia++) {
                                int nbf  = bp_chunks(chunk).desc_(beta_desc_idx::nbf, ia);
                                int offs = bp_chunks(chunk).desc_(beta_desc_idx::offset, ia);
                                int ja   = bp_chunks(chunk).desc_(beta_desc_idx::ia, ia);

                                for (int i = 0; i < nbnd_loc; i++) {
                                    int j = spl_nbnd[i];

                                    for (int xi = 0; xi < nbf; xi++) {
                                        bp1(xi, i) = beta_psi(offs + xi, j);
                                        bp2(xi, i) = std::conj(bp1(xi, i)) * kp__->weight() *
                                                     kp__->band_occupancy(j + ispn * ctx_.num_fv_states());
                                    }
                                }

                                linalg<CPU>::gemm(0, 1, nbf, nbf, nbnd_loc, linalg_const<double_complex>::one(),
                                                  &bp1(0, 0), bp1.ld(), &bp2(0, 0), bp2.ld(),
                                                  linalg_const<double_complex>::one(),
                                                  &density_matrix__(0, 0, ispn, ja),
                                                  density_matrix__.ld());
                            }
                        }
                    }
                }
            }
        } else {
            for (int chunk = 0; chunk < bp_chunks.num_chunks(); chunk++) {
                kp__->beta_projectors().generate(chunk);

                /* number of beta projectors */
                int nbeta = bp_chunks(chunk).num_beta_;

                /* total number of occupied bands */
                int nbnd = kp__->num_occupied_bands();

                splindex<block> spl_nbnd(nbnd, kp__->comm().size(), kp__->comm().rank());
                int nbnd_loc = spl_nbnd.local_size();

                /* auxiliary arrays */
                mdarray<double_complex, 3> bp1(nbeta, nbnd_loc, 2);
                mdarray<double_complex, 3> bp2(nbeta, nbnd_loc, 2);

                for (int ispn = 0; ispn < ctx_.num_spins(); ispn++) {
                    /* compute <beta|psi> */
                    auto beta_psi = kp__->beta_projectors().inner<T>(chunk, kp__->spinor_wave_functions(ispn), 0, nbnd);
                    #pragma omp parallel for schedule(static)
                    for (int i = 0; i < nbnd_loc; i++) {
                        int j = spl_nbnd[i];

                        for (int m = 0; m < nbeta; m++) {
                            bp1(m, i, ispn) = beta_psi(m, j);
                            bp2(m, i, ispn) = std::conj(beta_psi(m, j)) * kp__->weight() * kp__->band_occupancy(j);
                        }
                    }
                }
                for (int ia = 0; ia < bp_chunks(chunk).num_atoms_; ia++) {
                    int nbf  = bp_chunks(chunk).desc_(beta_desc_idx::nbf, ia);
                    int offs = bp_chunks(chunk).desc_(beta_desc_idx::offset, ia);
                    int ja   = bp_chunks(chunk).desc_(beta_desc_idx::ia, ia);
                    if (ctx_.unit_cell().atom(ja).type().pp_desc().spin_orbit_coupling) {
                        mdarray<double_complex, 3> bp3(nbf, nbnd_loc, 2);
                        bp3.zero();
                        /* We already have the <beta|psi> but we need to rotate
                         *  them when the spin orbit interaction is included in the
                         *  pseudo potential.
                         *
                         *  We rotate \f[\langle\beta|\psi\rangle\f] accordingly by multiplying it with
                         *  the \f[f^{\sigma\sigma^{'}}_{\xi,\xi^'}\f]
                         */

                        for (int xi1 = 0; xi1 < nbf; xi1++) {
                            for (int i = 0; i < nbnd_loc; i++) {
                                int j = spl_nbnd[i];
                                for (int xi1p = 0; xi1p < nbf; xi1p++) {
                                    if (ctx_.unit_cell().atom(ja).type().compare_index_beta_functions(xi1, xi1p)) {
                                        bp3(xi1, i, 0) +=
                                            bp1(offs + xi1p, i, 0) *
                                                ctx_.unit_cell().atom(ja).type().f_coefficients(xi1, xi1p, 0, 0) +
                                            bp1(offs + xi1p, i, 1) *
                                                ctx_.unit_cell().atom(ja).type().f_coefficients(xi1, xi1p, 0, 1);
                                        bp3(xi1, i, 1) +=
                                            bp1(offs + xi1p, i, 0) *
                                                ctx_.unit_cell().atom(ja).type().f_coefficients(xi1, xi1p, 1, 0) +
                                            bp1(offs + xi1p, i, 1) *
                                                ctx_.unit_cell().atom(ja).type().f_coefficients(xi1, xi1p, 1, 1);
                                    }
                                }
                            }
                        }

                        for (int xi1 = 0; xi1 < nbf; xi1++) {
                            for (int i = 0; i < nbnd_loc; i++) {
                                bp1(offs + xi1, i, 0) = bp3(xi1, i, 0);
                                bp1(offs + xi1, i, 1) = bp3(xi1, i, 1);
                            }
                        }

                        bp3.zero();

                        for (int xi1 = 0; xi1 < nbf; xi1++) {
                            for (int i = 0; i < nbnd_loc; i++) {
                                for (int xi1p = 0; xi1p < nbf; xi1p++) {
                                    if (ctx_.unit_cell().atom(ja).type().compare_index_beta_functions(xi1, xi1p)) {
                                        bp3(xi1, i, 0) +=
                                            bp2(offs + xi1p, i, 0) *
                                                ctx_.unit_cell().atom(ja).type().f_coefficients(xi1p, xi1, 0, 0) +
                                            bp2(offs + xi1p, i, 1) *
                                                ctx_.unit_cell().atom(ja).type().f_coefficients(xi1p, xi1, 1, 0);
                                        bp3(xi1, i, 1) +=
                                            bp2(offs + xi1p, i, 0) *
                                                ctx_.unit_cell().atom(ja).type().f_coefficients(xi1p, xi1, 0, 1) +
                                            bp2(offs + xi1p, i, 1) *
                                                ctx_.unit_cell().atom(ja).type().f_coefficients(xi1p, xi1, 1, 1);
                                    }
                                }
                            }
                        }

                        for (int xi1 = 0; xi1 < nbf; xi1++) {
                            for (int i = 0; i < nbnd_loc; i++) {
                                bp2(offs + xi1, i, 0) = bp3(xi1, i, 0);
                                bp2(offs + xi1, i, 1) = bp3(xi1, i, 1);
                            }
                        }
                    }
                }

                if (nbnd_loc) {
                    #pragma omp parallel for
                    for (int ia = 0; ia < bp_chunks(chunk).num_atoms_; ia++) {
                        int nbf  = bp_chunks(chunk).desc_(beta_desc_idx::nbf, ia);
                        int offs = bp_chunks(chunk).desc_(beta_desc_idx::offset, ia);
                        int ja   = bp_chunks(chunk).desc_(beta_desc_idx::ia, ia);
                        /* compute diagonal spin blocks */
                        for (int ispn = 0; ispn < 2; ispn++) {
                            linalg<CPU>::gemm(0, 1, nbf, nbf, nbnd_loc, linalg_const<double_complex>::one(),
                                              &bp1(offs, 0, ispn), bp1.ld(), &bp2(offs, 0, ispn), bp2.ld(),
                                              linalg_const<double_complex>::one(), &density_matrix__(0, 0, ispn, ja),
                                              density_matrix__.ld());
                        }
                        /* off-diagonal spin block */
                        linalg<CPU>::gemm(0, 1, nbf, nbf, nbnd_loc, linalg_const<double_complex>::one(),
                                          &bp1(offs, 0, 0), bp1.ld(), &bp2(offs, 0, 1), bp2.ld(),
                                          linalg_const<double_complex>::one(), &density_matrix__(0, 0, 2, ja),
                                          density_matrix__.ld());
                    }
                }
            }
        }
        kp__->beta_projectors().dismiss();
    }
}
<|endoftext|>


<commit_before><commit_msg>loplugin:unreffun<commit_after><|endoftext|>


<commit_before>void Config()
{
    // 7-DEC-2000 09:00
    // Switch on Transition Radiation simulation. 6/12/00 18:00
    // iZDC=1  7/12/00 09:00
    // ThetaRange is (0., 180.). It was (0.28,179.72) 7/12/00 09:00
    // Theta range given through pseudorapidity limits 22/6/2001

    // Set Random Number seed
    // gRandom->SetSeed(12345);

    new     AliGeant3("C++ Interface to Geant3");

    if (!gSystem->Getenv("CONFIG_FILE"))
    {
        TFile  *rootfile = new TFile("galice.root", "recreate");

        rootfile->SetCompressionLevel(2);
    }

    TGeant3 *geant3 = (TGeant3 *) gMC;

    //
    // Set External decayer
    AliDecayer *decayer = new AliDecayerPythia();

    decayer->SetForceDecay(kAll);
    decayer->Init();
    gMC->SetExternalDecayer(decayer);
    //
    //
    //=======================================================================
    // ******* GEANT STEERING parameters FOR ALICE SIMULATION *******
    geant3->SetTRIG(1);         //Number of events to be processed
    geant3->SetSWIT(4, 10);
    geant3->SetDEBU(0, 0, 1);
    //geant3->SetSWIT(2,2);
    geant3->SetDCAY(1);
    geant3->SetPAIR(1);
    geant3->SetCOMP(1);
    geant3->SetPHOT(1);
    geant3->SetPFIS(0);
    geant3->SetDRAY(0);
    geant3->SetANNI(1);
    geant3->SetBREM(1);
    geant3->SetMUNU(1);
    geant3->SetCKOV(1);
    geant3->SetHADR(1);         //Select pure GEANH (HADR 1) or GEANH/NUCRIN (HADR 3)
    geant3->SetLOSS(2);
    geant3->SetMULS(1);
    geant3->SetRAYL(1);
    geant3->SetAUTO(1);         //Select automatic STMIN etc... calc. (AUTO 1) or manual (AUTO 0)
    geant3->SetABAN(0);         //Restore 3.16 behaviour for abandoned tracks
    geant3->SetOPTI(2);         //Select optimisation level for GEANT geometry searches (0,1,2)
    geant3->SetERAN(5.e-7);

    Float_t cut = 1.e-3;        // 1MeV cut by default
    Float_t tofmax = 1.e10;

    //             GAM ELEC NHAD CHAD MUON EBREM MUHAB EDEL MUDEL MUPA TOFMAX
    geant3->SetCUTS(cut, cut, cut, cut, cut, cut, cut, cut, cut, cut,
                    tofmax);
    //
    //=======================================================================
    // ************* STEERING parameters FOR ALICE SIMULATION **************
    // --- Specify event type to be tracked through the ALICE setup
    // --- All positions are in cm, angles in degrees, and P and E in GeV
    if (gSystem->Getenv("CONFIG_NPARTICLES"))
    {
        int     nParticles = atoi(gSystem->Getenv("CONFIG_NPARTICLES"));
    } else
    {
        int     nParticles = 50;
    }
    AliGenHIJINGpara *gener = new AliGenHIJINGpara(nParticles);

    gener->SetMomentumRange(0, 999);
    gener->SetPhiRange(0, 360);
    // Set pseudorapidity range from -8 to 8.
    Float_t thmin = EtaToTheta(8);   // theta min. <---> eta max
    Float_t thmax = EtaToTheta(-8);  // theta max. <---> eta min
    gener->SetThetaRange(thmin,thmax);
    gener->SetOrigin(0, 0, 0);  //vertex position
    gener->SetSigma(0, 0, 0);   //Sigma in (X,Y,Z) (cm) on IP position
    gener->Init();
    //
    // Activate this line if you want the vertex smearing to happen
    // track by track
    //
    //gener->SetVertexSmear(perTrack);

    gAlice->SetField(-999, 2);  //Specify maximum magnetic field in Tesla (neg. ==> default field)

    Int_t   iABSO = 1;
    Int_t   iCASTOR = 1;
    Int_t   iDIPO = 1;
    Int_t   iFMD = 1;
    Int_t   iFRAME = 1;
    Int_t   iHALL = 1;
    Int_t   iITS = 1;
    Int_t   iMAG = 1;
    Int_t   iMUON = 1;
    Int_t   iPHOS = 1;
    Int_t   iPIPE = 1;
    Int_t   iPMD = 1;
    Int_t   iRICH = 1;
    Int_t   iSHIL = 1;
    Int_t   iSTART = 1;
    Int_t   iTOF = 1;
    Int_t   iTPC = 1;
    Int_t   iTRD = 1;
    Int_t   iZDC = 1;
    Int_t   iEMCAL = 0;

    //=================== Alice BODY parameters =============================
    AliBODY *BODY = new AliBODY("BODY", "Alice envelop");

    if (iMAG)
    {
        //=================== MAG parameters ============================
        // --- Start with Magnet since detector layouts may be depending ---
        // --- on the selected Magnet dimensions ---
        AliMAG *MAG = new AliMAG("MAG", "Magnet");
    }

    if (iABSO)
    {
        //=================== ABSO parameters ============================
        AliABSO *ABSO = new AliABSOv0("ABSO", "Muon Absorber");
    }

    if (iDIPO)
    {
        //=================== DIPO parameters ============================

        AliDIPO *DIPO = new AliDIPOv2("DIPO", "Dipole version 2");
    }

    if (iHALL)
    {
        //=================== HALL parameters ============================

        AliHALL *HALL = new AliHALL("HALL", "Alice Hall");
    }

    if (iFRAME)
    {
        //=================== FRAME parameters ============================

        AliFRAME *FRAME = new AliFRAMEv2("FRAME", "Space Frame");

    }

    if (iSHIL)
    {
        //=================== SHIL parameters ============================

        AliSHIL *SHIL = new AliSHILvF("SHIL", "Shielding");
    }

    if (iPIPE)
    {
        //=================== PIPE parameters ============================

        AliPIPE *PIPE = new AliPIPEv0("PIPE", "Beam Pipe");
    }

  if(iITS) {

//=================== ITS parameters ============================
    //
    // As the innermost detector in ALICE, the Inner Tracking System "impacts" on
    // almost all other detectors. This involves the fact that the ITS geometry
    // still has several options to be followed in parallel in order to determine
    // the best set-up which minimizes the induced background. All the geometries
    // available to date are described in the following. Read carefully the comments
    // and use the default version (the only one uncommented) unless you are making
    // comparisons and you know what you are doing. In this case just uncomment the
    // ITS geometry you want to use and run Aliroot.
    //
    // Detailed geometries:
    //
    //
    //AliITS *ITS  = new AliITSv5symm("ITS","Updated ITS TDR detailed version with symmetric services");
    //
    //AliITS *ITS  = new AliITSv5asymm("ITS","Updates ITS TDR detailed version with asymmetric services");
    //
    AliITSvPPRasymm *ITS  = new AliITSvPPRasymm("ITS","New ITS PPR detailed version with asymmetric services");
    ITS->SetMinorVersion(2);					 // don't touch this parameter if you're not an ITS developer
    ITS->SetReadDet(kFALSE);					 // don't touch this parameter if you're not an ITS developer
    //    ITS->SetWriteDet("$ALICE_ROOT/ITS/ITSgeometry_vPPRasymm2.det");  // don't touch this parameter if you're not an ITS developer
    ITS->SetThicknessDet1(200.);   // detector thickness on layer 1 must be in the range [100,300]
    ITS->SetThicknessDet2(200.);   // detector thickness on layer 2 must be in the range [100,300]
    ITS->SetThicknessChip1(200.);  // chip thickness on layer 1 must be in the range [150,300]
    ITS->SetThicknessChip2(200.);  // chip thickness on layer 2 must be in the range [150,300]
    ITS->SetRails(1);	     // 1 --> rails in ; 0 --> rails out
    ITS->SetCoolingFluid(1);   // 1 --> water ; 0 --> freon
    //
    //AliITSvPPRsymm *ITS  = new AliITSvPPRsymm("ITS","New ITS PPR detailed version with symmetric services");
    //ITS->SetMinorVersion(2);                                       // don't touch this parameter if you're not an ITS developer
    //ITS->SetReadDet(kFALSE);                                       // don't touch this parameter if you're not an ITS developer
    //ITS->SetWriteDet("$ALICE_ROOT/ITS/ITSgeometry_vPPRsymm2.det"); // don't touch this parameter if you're not an ITS developer
    //ITS->SetThicknessDet1(200.);   // detector thickness on layer 1 must be in the range [100,300]
    //ITS->SetThicknessDet2(200.);   // detector thickness on layer 2 must be in the range [100,300]
    //ITS->SetThicknessChip1(200.);  // chip thickness on layer 1 must be in the range [150,300]
    //ITS->SetThicknessChip2(200.);  // chip thickness on layer 2 must be in the range [150,300]
    //ITS->SetRails(1);              // 1 --> rails in ; 0 --> rails out
    //ITS->SetCoolingFluid(1);       // 1 --> water ; 0 --> freon
    //
    //
    // Coarse geometries (warning: no hits are produced with these coarse geometries and they unuseful
    // for reconstruction !):
    //
    //
    //AliITSvPPRcoarseasymm *ITS  = new AliITSvPPRcoarseasymm("ITS","New ITS PPR coarse version with asymmetric services");
    //ITS->SetRails(1);                // 1 --> rails in ; 0 --> rails out
    //ITS->SetSupportMaterial(0);      // 0 --> Copper ; 1 --> Aluminum ; 2 --> Carbon
    //
    //AliITS *ITS  = new AliITSvPPRcoarsesymm("ITS","New ITS PPR coarse version with symmetric services");
    //ITS->SetRails(1);                // 1 --> rails in ; 0 --> rails out
    //ITS->SetSupportMaterial(0);      // 0 --> Copper ; 1 --> Aluminum ; 2 --> Carbon
    //
    //
    //
    // Geant3 <-> EUCLID conversion
    // ============================
    //
    // SetEUCLID is a flag to output (=1) or not to output (=0) both geometry and
    // media to two ASCII files (called by default ITSgeometry.euc and
    // ITSgeometry.tme) in a format understandable to the CAD system EUCLID.
    // The default (=0) means that you dont want to use this facility.
    //
    ITS->SetEUCLID(0);
  }

    if (iTPC)
    {
        //============================ TPC parameters ================================
        // --- This allows the user to specify sectors for the SLOW (TPC geometry 2)
        // --- Simulator. SecAL (SecAU) <0 means that ALL lower (upper)
        // --- sectors are specified, any value other than that requires at least one
        // --- sector (lower or upper)to be specified!
        // --- Reminder: sectors 1-24 are lower sectors (1-12 -> z>0, 13-24 -> z<0)
        // ---           sectors 25-72 are the upper ones (25-48 -> z>0, 49-72 -> z<0)
        // --- SecLows - number of lower sectors specified (up to 6)
        // --- SecUps - number of upper sectors specified (up to 12)
        // --- Sens - sensitive strips for the Slow Simulator !!!
        // --- This does NOT work if all S or L-sectors are specified, i.e.
        // --- if SecAL or SecAU < 0
        //
        //
        //-----------------------------------------------------------------------------

        //  gROOT->LoadMacro("SetTPCParam.C");
        //  AliTPCParam *param = SetTPCParam();
        AliTPC *TPC = new AliTPCv2("TPC", "Default");

        // All sectors included
        TPC->SetSecAL(-1);
        TPC->SetSecAU(-1);

    }

    if (iTOF)
    {
        //=================== TOF parameters ============================
        AliTOF *TOF = new AliTOFv2("TOF", "normal TOF");
    }

    if (iRICH)
    {
        //=================== RICH parameters ===========================
        AliRICH *RICH = new AliRICHv1("RICH", "normal RICH");

    }

    if (iZDC)
    {
        //=================== ZDC parameters ============================

        AliZDC *ZDC = new AliZDCv2("ZDC", "normal ZDC");
    }

    if (iCASTOR)
    {
        //=================== CASTOR parameters ============================

        AliCASTOR *CASTOR = new AliCASTORv1("CASTOR", "normal CASTOR");
    }

    if (iTRD)
    {
        //=================== TRD parameters ============================

        AliTRD *TRD = new AliTRDv1("TRD", "TRD slow simulator");

        // Select the gas mixture (0: 97% Xe + 3% isobutane, 1: 90% Xe + 10% CO2)
        TRD->SetGasMix(1);

        // With hole in front of PHOS
        TRD->SetPHOShole();
        // With hole in front of RICH
        TRD->SetRICHhole();
        // Switch on TR
        AliTRDsim *TRDsim = TRD->CreateTR();
    }

    if (iFMD)
    {
        //=================== FMD parameters ============================

        AliFMD *FMD = new AliFMDv1("FMD", "normal FMD");
        FMD->SetRingsSi1(128);
        FMD->SetRingsSi2(64);
        FMD->SetSectorsSi1(20);
        FMD->SetSectorsSi2(24);
   }

    if (iMUON)
    {
        //=================== MUON parameters ===========================

        AliMUON *MUON = new AliMUONv1("MUON", "default");
    }
    //=================== PHOS parameters ===========================

    if (iPHOS)
    {
        AliPHOS *PHOS = new AliPHOSv1("PHOS", "GPS2");
    }

    if (iPMD)
    {
        //=================== PMD parameters ============================

        AliPMD *PMD = new AliPMDv1("PMD", "normal PMD");

        PMD->SetPAR(1., 1., 0.8, 0.02);
        PMD->SetIN(6., 18., -580., 27., 27.);
        PMD->SetGEO(0.0, 0.2, 4.);
        PMD->SetPadSize(0.8, 1.0, 1.0, 1.5);

    }

    if (iEMCAL && !iRICH)
    {
        //=================== EMCAL parameters ============================
        AliEMCAL *EMCAL = new AliEMCALv1("EMCAL", "EMCALArch1a");
    }

    if (iSTART)
    {
        //=================== START parameters ============================
        AliSTART *START = new AliSTARTv1("START", "START Detector");
    }

}

Float_t EtaToTheta(Float_t arg){
  return (180./TMath::Pi())*2.*atan(exp(-arg));
}
<commit_msg>Number of RingsSi1 set to 256<commit_after>void Config()
{
    // 7-DEC-2000 09:00
    // Switch on Transition Radiation simulation. 6/12/00 18:00
    // iZDC=1  7/12/00 09:00
    // ThetaRange is (0., 180.). It was (0.28,179.72) 7/12/00 09:00
    // Theta range given through pseudorapidity limits 22/6/2001

    // Set Random Number seed
    // gRandom->SetSeed(12345);

    new     AliGeant3("C++ Interface to Geant3");

    if (!gSystem->Getenv("CONFIG_FILE"))
    {
        TFile  *rootfile = new TFile("galice.root", "recreate");

        rootfile->SetCompressionLevel(2);
    }

    TGeant3 *geant3 = (TGeant3 *) gMC;

    //
    // Set External decayer
    AliDecayer *decayer = new AliDecayerPythia();

    decayer->SetForceDecay(kAll);
    decayer->Init();
    gMC->SetExternalDecayer(decayer);
    //
    //
    //=======================================================================
    // ******* GEANT STEERING parameters FOR ALICE SIMULATION *******
    geant3->SetTRIG(1);         //Number of events to be processed
    geant3->SetSWIT(4, 10);
    geant3->SetDEBU(0, 0, 1);
    //geant3->SetSWIT(2,2);
    geant3->SetDCAY(1);
    geant3->SetPAIR(1);
    geant3->SetCOMP(1);
    geant3->SetPHOT(1);
    geant3->SetPFIS(0);
    geant3->SetDRAY(0);
    geant3->SetANNI(1);
    geant3->SetBREM(1);
    geant3->SetMUNU(1);
    geant3->SetCKOV(1);
    geant3->SetHADR(1);         //Select pure GEANH (HADR 1) or GEANH/NUCRIN (HADR 3)
    geant3->SetLOSS(2);
    geant3->SetMULS(1);
    geant3->SetRAYL(1);
    geant3->SetAUTO(1);         //Select automatic STMIN etc... calc. (AUTO 1) or manual (AUTO 0)
    geant3->SetABAN(0);         //Restore 3.16 behaviour for abandoned tracks
    geant3->SetOPTI(2);         //Select optimisation level for GEANT geometry searches (0,1,2)
    geant3->SetERAN(5.e-7);

    Float_t cut = 1.e-3;        // 1MeV cut by default
    Float_t tofmax = 1.e10;

    //             GAM ELEC NHAD CHAD MUON EBREM MUHAB EDEL MUDEL MUPA TOFMAX
    geant3->SetCUTS(cut, cut, cut, cut, cut, cut, cut, cut, cut, cut,
                    tofmax);
    //
    //=======================================================================
    // ************* STEERING parameters FOR ALICE SIMULATION **************
    // --- Specify event type to be tracked through the ALICE setup
    // --- All positions are in cm, angles in degrees, and P and E in GeV
    if (gSystem->Getenv("CONFIG_NPARTICLES"))
    {
        int     nParticles = atoi(gSystem->Getenv("CONFIG_NPARTICLES"));
    } else
    {
        int     nParticles = 50;
    }
    AliGenHIJINGpara *gener = new AliGenHIJINGpara(nParticles);

    gener->SetMomentumRange(0, 999);
    gener->SetPhiRange(0, 360);
    // Set pseudorapidity range from -8 to 8.
    Float_t thmin = EtaToTheta(8);   // theta min. <---> eta max
    Float_t thmax = EtaToTheta(-8);  // theta max. <---> eta min
    gener->SetThetaRange(thmin,thmax);
    gener->SetOrigin(0, 0, 0);  //vertex position
    gener->SetSigma(0, 0, 0);   //Sigma in (X,Y,Z) (cm) on IP position
    gener->Init();
    //
    // Activate this line if you want the vertex smearing to happen
    // track by track
    //
    //gener->SetVertexSmear(perTrack);

    gAlice->SetField(-999, 2);  //Specify maximum magnetic field in Tesla (neg. ==> default field)

    Int_t   iABSO = 1;
    Int_t   iCASTOR = 1;
    Int_t   iDIPO = 1;
    Int_t   iFMD = 1;
    Int_t   iFRAME = 1;
    Int_t   iHALL = 1;
    Int_t   iITS = 1;
    Int_t   iMAG = 1;
    Int_t   iMUON = 1;
    Int_t   iPHOS = 1;
    Int_t   iPIPE = 1;
    Int_t   iPMD = 1;
    Int_t   iRICH = 1;
    Int_t   iSHIL = 1;
    Int_t   iSTART = 1;
    Int_t   iTOF = 1;
    Int_t   iTPC = 1;
    Int_t   iTRD = 1;
    Int_t   iZDC = 1;
    Int_t   iEMCAL = 0;

    //=================== Alice BODY parameters =============================
    AliBODY *BODY = new AliBODY("BODY", "Alice envelop");

    if (iMAG)
    {
        //=================== MAG parameters ============================
        // --- Start with Magnet since detector layouts may be depending ---
        // --- on the selected Magnet dimensions ---
        AliMAG *MAG = new AliMAG("MAG", "Magnet");
    }

    if (iABSO)
    {
        //=================== ABSO parameters ============================
        AliABSO *ABSO = new AliABSOv0("ABSO", "Muon Absorber");
    }

    if (iDIPO)
    {
        //=================== DIPO parameters ============================

        AliDIPO *DIPO = new AliDIPOv2("DIPO", "Dipole version 2");
    }

    if (iHALL)
    {
        //=================== HALL parameters ============================

        AliHALL *HALL = new AliHALL("HALL", "Alice Hall");
    }

    if (iFRAME)
    {
        //=================== FRAME parameters ============================

        AliFRAME *FRAME = new AliFRAMEv2("FRAME", "Space Frame");

    }

    if (iSHIL)
    {
        //=================== SHIL parameters ============================

        AliSHIL *SHIL = new AliSHILvF("SHIL", "Shielding");
    }

    if (iPIPE)
    {
        //=================== PIPE parameters ============================

        AliPIPE *PIPE = new AliPIPEv0("PIPE", "Beam Pipe");
    }

  if(iITS) {

//=================== ITS parameters ============================
    //
    // As the innermost detector in ALICE, the Inner Tracking System "impacts" on
    // almost all other detectors. This involves the fact that the ITS geometry
    // still has several options to be followed in parallel in order to determine
    // the best set-up which minimizes the induced background. All the geometries
    // available to date are described in the following. Read carefully the comments
    // and use the default version (the only one uncommented) unless you are making
    // comparisons and you know what you are doing. In this case just uncomment the
    // ITS geometry you want to use and run Aliroot.
    //
    // Detailed geometries:
    //
    //
    //AliITS *ITS  = new AliITSv5symm("ITS","Updated ITS TDR detailed version with symmetric services");
    //
    //AliITS *ITS  = new AliITSv5asymm("ITS","Updates ITS TDR detailed version with asymmetric services");
    //
    AliITSvPPRasymm *ITS  = new AliITSvPPRasymm("ITS","New ITS PPR detailed version with asymmetric services");
    ITS->SetMinorVersion(2);					 // don't touch this parameter if you're not an ITS developer
    ITS->SetReadDet(kFALSE);					 // don't touch this parameter if you're not an ITS developer
    //    ITS->SetWriteDet("$ALICE_ROOT/ITS/ITSgeometry_vPPRasymm2.det");  // don't touch this parameter if you're not an ITS developer
    ITS->SetThicknessDet1(200.);   // detector thickness on layer 1 must be in the range [100,300]
    ITS->SetThicknessDet2(200.);   // detector thickness on layer 2 must be in the range [100,300]
    ITS->SetThicknessChip1(200.);  // chip thickness on layer 1 must be in the range [150,300]
    ITS->SetThicknessChip2(200.);  // chip thickness on layer 2 must be in the range [150,300]
    ITS->SetRails(1);	     // 1 --> rails in ; 0 --> rails out
    ITS->SetCoolingFluid(1);   // 1 --> water ; 0 --> freon
    //
    //AliITSvPPRsymm *ITS  = new AliITSvPPRsymm("ITS","New ITS PPR detailed version with symmetric services");
    //ITS->SetMinorVersion(2);                                       // don't touch this parameter if you're not an ITS developer
    //ITS->SetReadDet(kFALSE);                                       // don't touch this parameter if you're not an ITS developer
    //ITS->SetWriteDet("$ALICE_ROOT/ITS/ITSgeometry_vPPRsymm2.det"); // don't touch this parameter if you're not an ITS developer
    //ITS->SetThicknessDet1(200.);   // detector thickness on layer 1 must be in the range [100,300]
    //ITS->SetThicknessDet2(200.);   // detector thickness on layer 2 must be in the range [100,300]
    //ITS->SetThicknessChip1(200.);  // chip thickness on layer 1 must be in the range [150,300]
    //ITS->SetThicknessChip2(200.);  // chip thickness on layer 2 must be in the range [150,300]
    //ITS->SetRails(1);              // 1 --> rails in ; 0 --> rails out
    //ITS->SetCoolingFluid(1);       // 1 --> water ; 0 --> freon
    //
    //
    // Coarse geometries (warning: no hits are produced with these coarse geometries and they unuseful
    // for reconstruction !):
    //
    //
    //AliITSvPPRcoarseasymm *ITS  = new AliITSvPPRcoarseasymm("ITS","New ITS PPR coarse version with asymmetric services");
    //ITS->SetRails(1);                // 1 --> rails in ; 0 --> rails out
    //ITS->SetSupportMaterial(0);      // 0 --> Copper ; 1 --> Aluminum ; 2 --> Carbon
    //
    //AliITS *ITS  = new AliITSvPPRcoarsesymm("ITS","New ITS PPR coarse version with symmetric services");
    //ITS->SetRails(1);                // 1 --> rails in ; 0 --> rails out
    //ITS->SetSupportMaterial(0);      // 0 --> Copper ; 1 --> Aluminum ; 2 --> Carbon
    //
    //
    //
    // Geant3 <-> EUCLID conversion
    // ============================
    //
    // SetEUCLID is a flag to output (=1) or not to output (=0) both geometry and
    // media to two ASCII files (called by default ITSgeometry.euc and
    // ITSgeometry.tme) in a format understandable to the CAD system EUCLID.
    // The default (=0) means that you dont want to use this facility.
    //
    ITS->SetEUCLID(0);
  }

    if (iTPC)
    {
        //============================ TPC parameters ================================
        // --- This allows the user to specify sectors for the SLOW (TPC geometry 2)
        // --- Simulator. SecAL (SecAU) <0 means that ALL lower (upper)
        // --- sectors are specified, any value other than that requires at least one
        // --- sector (lower or upper)to be specified!
        // --- Reminder: sectors 1-24 are lower sectors (1-12 -> z>0, 13-24 -> z<0)
        // ---           sectors 25-72 are the upper ones (25-48 -> z>0, 49-72 -> z<0)
        // --- SecLows - number of lower sectors specified (up to 6)
        // --- SecUps - number of upper sectors specified (up to 12)
        // --- Sens - sensitive strips for the Slow Simulator !!!
        // --- This does NOT work if all S or L-sectors are specified, i.e.
        // --- if SecAL or SecAU < 0
        //
        //
        //-----------------------------------------------------------------------------

        //  gROOT->LoadMacro("SetTPCParam.C");
        //  AliTPCParam *param = SetTPCParam();
        AliTPC *TPC = new AliTPCv2("TPC", "Default");

        // All sectors included
        TPC->SetSecAL(-1);
        TPC->SetSecAU(-1);

    }

    if (iTOF)
    {
        //=================== TOF parameters ============================
        AliTOF *TOF = new AliTOFv2("TOF", "normal TOF");
    }

    if (iRICH)
    {
        //=================== RICH parameters ===========================
        AliRICH *RICH = new AliRICHv1("RICH", "normal RICH");

    }

    if (iZDC)
    {
        //=================== ZDC parameters ============================

        AliZDC *ZDC = new AliZDCv2("ZDC", "normal ZDC");
    }

    if (iCASTOR)
    {
        //=================== CASTOR parameters ============================

        AliCASTOR *CASTOR = new AliCASTORv1("CASTOR", "normal CASTOR");
    }

    if (iTRD)
    {
        //=================== TRD parameters ============================

        AliTRD *TRD = new AliTRDv1("TRD", "TRD slow simulator");

        // Select the gas mixture (0: 97% Xe + 3% isobutane, 1: 90% Xe + 10% CO2)
        TRD->SetGasMix(1);

        // With hole in front of PHOS
        TRD->SetPHOShole();
        // With hole in front of RICH
        TRD->SetRICHhole();
        // Switch on TR
        AliTRDsim *TRDsim = TRD->CreateTR();
    }

    if (iFMD)
    {
        //=================== FMD parameters ============================

        AliFMD *FMD = new AliFMDv1("FMD", "normal FMD");
        FMD->SetRingsSi1(256);
        FMD->SetRingsSi2(64);
        FMD->SetSectorsSi1(20);
        FMD->SetSectorsSi2(24);
   }

    if (iMUON)
    {
        //=================== MUON parameters ===========================

        AliMUON *MUON = new AliMUONv1("MUON", "default");
    }
    //=================== PHOS parameters ===========================

    if (iPHOS)
    {
        AliPHOS *PHOS = new AliPHOSv1("PHOS", "GPS2");
    }

    if (iPMD)
    {
        //=================== PMD parameters ============================

        AliPMD *PMD = new AliPMDv1("PMD", "normal PMD");

        PMD->SetPAR(1., 1., 0.8, 0.02);
        PMD->SetIN(6., 18., -580., 27., 27.);
        PMD->SetGEO(0.0, 0.2, 4.);
        PMD->SetPadSize(0.8, 1.0, 1.0, 1.5);

    }

    if (iEMCAL && !iRICH)
    {
        //=================== EMCAL parameters ============================
        AliEMCAL *EMCAL = new AliEMCALv1("EMCAL", "EMCALArch1a");
    }

    if (iSTART)
    {
        //=================== START parameters ============================
        AliSTART *START = new AliSTARTv1("START", "START Detector");
    }

}

Float_t EtaToTheta(Float_t arg){
  return (180./TMath::Pi())*2.*atan(exp(-arg));
}
<|endoftext|>


<commit_before>//===--- Platform.cpp - Implement platform-related helpers ----------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/Basic/Platform.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/VersionTuple.h"

using namespace swift;

bool swift::tripleIsiOSSimulator(const llvm::Triple &triple) {
  llvm::Triple::ArchType arch = triple.getArch();
  return (triple.isiOS() &&
          // FIXME: transitional, this should eventually stop testing arch, and
          // switch to only checking the -environment field.
          (triple.isSimulatorEnvironment() ||
           arch == llvm::Triple::x86 || arch == llvm::Triple::x86_64));
}

bool swift::tripleIsAppleTVSimulator(const llvm::Triple &triple) {
  llvm::Triple::ArchType arch = triple.getArch();
  return (triple.isTvOS() &&
          // FIXME: transitional, this should eventually stop testing arch, and
          // switch to only checking the -environment field.
          (triple.isSimulatorEnvironment() ||
           arch == llvm::Triple::x86 || arch == llvm::Triple::x86_64));
}

bool swift::tripleIsWatchSimulator(const llvm::Triple &triple) {
  llvm::Triple::ArchType arch = triple.getArch();
  return (triple.isWatchOS() &&
          // FIXME: transitional, this should eventually stop testing arch, and
          // switch to only checking the -environment field.
          (triple.isSimulatorEnvironment() ||
           arch == llvm::Triple::x86 || arch == llvm::Triple::x86_64));
}

bool swift::tripleIsAnySimulator(const llvm::Triple &triple) {
  // FIXME: transitional, this should eventually just use the -environment
  // field.
  return triple.isSimulatorEnvironment() ||
    tripleIsiOSSimulator(triple) ||
    tripleIsWatchSimulator(triple) ||
    tripleIsAppleTVSimulator(triple);
}

bool swift::tripleRequiresRPathForSwiftInOS(const llvm::Triple &triple) {
  if (triple.isMacOSX()) {
    // macOS 10.14.4 contains a copy of Swift, but the linker will still use an
    // rpath-based install name until 10.15.
    return triple.isMacOSXVersionLT(10, 15);

  } else if (triple.isiOS()) {
    return triple.isOSVersionLT(12, 2);

  } else if (triple.isWatchOS()) {
    return triple.isOSVersionLT(5, 2);
  }

  // Other platforms don't have Swift installed as part of the OS by default.
  return false;
}

DarwinPlatformKind swift::getDarwinPlatformKind(const llvm::Triple &triple) {
  if (triple.isiOS()) {
    if (triple.isTvOS()) {
      if (tripleIsAppleTVSimulator(triple))
        return DarwinPlatformKind::TvOSSimulator;
      return DarwinPlatformKind::TvOS;
    }

    if (tripleIsiOSSimulator(triple))
      return DarwinPlatformKind::IPhoneOSSimulator;
    return DarwinPlatformKind::IPhoneOS;
  }

  if (triple.isWatchOS()) {
    if (tripleIsWatchSimulator(triple))
      return DarwinPlatformKind::WatchOSSimulator;
    return DarwinPlatformKind::WatchOS;
  }

  if (triple.isMacOSX())
    return DarwinPlatformKind::MacOS;

  llvm_unreachable("Unsupported Darwin platform");
}

DarwinPlatformKind swift::getNonSimulatorPlatform(DarwinPlatformKind platform) {
  switch (platform) {
  case DarwinPlatformKind::MacOS:
    return DarwinPlatformKind::MacOS;
  case DarwinPlatformKind::IPhoneOS:
  case DarwinPlatformKind::IPhoneOSSimulator:
    return DarwinPlatformKind::IPhoneOS;
  case DarwinPlatformKind::TvOS:
  case DarwinPlatformKind::TvOSSimulator:
    return DarwinPlatformKind::TvOS;
  case DarwinPlatformKind::WatchOS:
  case DarwinPlatformKind::WatchOSSimulator:
    return DarwinPlatformKind::WatchOS;
  }
  llvm_unreachable("Unsupported Darwin platform");
}

static StringRef getPlatformNameForDarwin(const DarwinPlatformKind platform) {
  switch (platform) {
  case DarwinPlatformKind::MacOS:
    return "macosx";
  case DarwinPlatformKind::IPhoneOS:
    return "iphoneos";
  case DarwinPlatformKind::IPhoneOSSimulator:
    return "iphonesimulator";
  case DarwinPlatformKind::TvOS:
    return "appletvos";
  case DarwinPlatformKind::TvOSSimulator:
    return "appletvsimulator";
  case DarwinPlatformKind::WatchOS:
    return "watchos";
  case DarwinPlatformKind::WatchOSSimulator:
    return "watchsimulator";
  }
  llvm_unreachable("Unsupported Darwin platform");
}

StringRef swift::getPlatformNameForTriple(const llvm::Triple &triple) {
  switch (triple.getOS()) {
  case llvm::Triple::UnknownOS:
    llvm_unreachable("unknown OS");
  case llvm::Triple::Ananas:
  case llvm::Triple::CloudABI:
  case llvm::Triple::DragonFly:
  case llvm::Triple::Emscripten:
  case llvm::Triple::Fuchsia:
  case llvm::Triple::KFreeBSD:
  case llvm::Triple::Lv2:
  case llvm::Triple::NetBSD:
  case llvm::Triple::OpenBSD:
  case llvm::Triple::Solaris:
  case llvm::Triple::Minix:
  case llvm::Triple::RTEMS:
  case llvm::Triple::NaCl:
  case llvm::Triple::CNK:
  case llvm::Triple::AIX:
  case llvm::Triple::CUDA:
  case llvm::Triple::NVCL:
  case llvm::Triple::AMDHSA:
  case llvm::Triple::ELFIAMCU:
  case llvm::Triple::Mesa3D:
  case llvm::Triple::Contiki:
  case llvm::Triple::AMDPAL:
  case llvm::Triple::HermitCore:
  case llvm::Triple::Hurd:
  case llvm::Triple::WASI:
    return "";
  case llvm::Triple::Darwin:
  case llvm::Triple::MacOSX:
  case llvm::Triple::IOS:
  case llvm::Triple::TvOS:
  case llvm::Triple::WatchOS:
    return getPlatformNameForDarwin(getDarwinPlatformKind(triple));
  case llvm::Triple::Linux:
    return triple.isAndroid() ? "android" : "linux";
  case llvm::Triple::FreeBSD:
    return "freebsd";
  case llvm::Triple::Win32:
    switch (triple.getEnvironment()) {
    case llvm::Triple::Cygnus:
      return "cygwin";
    case llvm::Triple::GNU:
      return "mingw";
    case llvm::Triple::MSVC:
    case llvm::Triple::Itanium:
      return "windows";
    default:
      llvm_unreachable("unsupported Windows environment");
    }
  case llvm::Triple::PS4:
    return "ps4";
  case llvm::Triple::Haiku:
    return "haiku";
  }
  llvm_unreachable("unsupported OS");
}

StringRef swift::getMajorArchitectureName(const llvm::Triple &Triple) {
  if (Triple.isOSLinux()) {
    switch(Triple.getSubArch()) {
    default:
      return Triple.getArchName();
      break;
    case llvm::Triple::SubArchType::ARMSubArch_v7:
      return "armv7";
      break;
    case llvm::Triple::SubArchType::ARMSubArch_v6:
      return "armv6";
      break;
    }
  } else {
    return Triple.getArchName();
  }
}

// The code below is responsible for normalizing target triples into the form
// used to name target-specific swiftmodule, swiftinterface, and swiftdoc files.
// If two triples have incompatible ABIs or can be distinguished by Swift #if
// declarations, they should normalize to different values.
//
// This code is only really used on platforms with toolchains supporting fat
// binaries (a single binary containing multiple architectures). On these
// platforms, this code should strip unnecessary details from target triple
// components and map synonyms to canonical values. Even values which don't need
// any special canonicalization should be documented here as comments.
//
// (Fallback behavior does not belong here; it should be implemented in code
// that calls this function, most importantly in SerializedModuleLoaderBase.)
//
// If you're trying to refer to this code to understand how Swift behaves and
// you're unfamiliar with LLVM internals, here's a cheat sheet for reading it:
//
// * llvm::Triple is the type for a target name. It's a bit of a misnomer,
//   because it can contain three or four values: arch-vendor-os[-environment].
//
// * In .Cases and .Case, the last argument is the value the arguments before it
//   map to. That is, `.Cases("bar", "baz", "foo")` will return "foo" if it sees
//   "bar" or "baz".
//
// * llvm::Optional is similar to a Swift Optional: it either contains a value
//   or represents the absence of one. `None` is equivalent to `nil`; leading
//   `*` is equivalent to trailing `!`; conversion to `bool` is a not-`None`
//   check.

static StringRef
getArchForAppleTargetSpecificModuleTriple(const llvm::Triple &triple) {
  auto tripleArchName = triple.getArchName();

  return llvm::StringSwitch<StringRef>(tripleArchName)
              .Cases("arm64", "aarch64", "arm64")
              .Cases("x86_64", "amd64", "x86_64")
              .Cases("i386", "i486", "i586", "i686", "i786", "i886", "i986",
                     "i386")
              .Cases("unknown", "", "unknown")
  // These values are also supported, but are handled by the default case below:
  //          .Case ("armv7s", "armv7s")
  //          .Case ("armv7k", "armv7k")
  //          .Case ("armv7", "armv7")
              .Default(tripleArchName);
}

static StringRef
getVendorForAppleTargetSpecificModuleTriple(const llvm::Triple &triple) {
  // We unconditionally normalize to "apple" because it's relatively common for
  // build systems to omit the vendor name or use an incorrect one like
  // "unknown". Most parts of the compiler ignore the vendor, so you might not
  // notice such a mistake.
  //
  // Please don't depend on this behavior--specify 'apple' if you're building
  // for an Apple platform.

  assert(triple.isOSDarwin() &&
         "shouldn't normalize non-Darwin triple to 'apple'");

  return "apple";
}

static StringRef
getOSForAppleTargetSpecificModuleTriple(const llvm::Triple &triple) {
  auto tripleOSName = triple.getOSName();

  // Truncate the OS name before the first digit. "Digit" here is ASCII '0'-'9'.
  auto tripleOSNameNoVersion = tripleOSName.take_until(llvm::isDigit);

  return llvm::StringSwitch<StringRef>(tripleOSNameNoVersion)
              .Cases("macos", "macosx", "darwin", "macos")
              .Cases("unknown", "", "unknown")
  // These values are also supported, but are handled by the default case below:
  //          .Case ("ios", "ios")
  //          .Case ("tvos", "tvos")
  //          .Case ("watchos", "watchos")
              .Default(tripleOSNameNoVersion);
}

static Optional<StringRef>
getEnvironmentForAppleTargetSpecificModuleTriple(const llvm::Triple &triple) {
  auto tripleEnvironment = triple.getEnvironmentName();

  // If the environment is empty, infer a "simulator" environment based on the
  // OS and architecture combination. This feature is deprecated and exists for
  // backwards compatibility only; build systems should pass the "simulator"
  // environment explicitly if they know they're building for a simulator.
  if (tripleEnvironment == "" && swift::tripleIsAnySimulator(triple))
    return StringRef("simulator");

  return llvm::StringSwitch<Optional<StringRef>>(tripleEnvironment)
              .Cases("unknown", "", None)
  // These values are also supported, but are handled by the default case below:
  //          .Case ("simulator", StringRef("simulator"))
              .Default(tripleEnvironment);
}

llvm::Triple swift::getTargetSpecificModuleTriple(const llvm::Triple &triple) {
  // isOSDarwin() returns true for all Darwin-style OSes, including macOS, iOS,
  // etc.
  if (triple.isOSDarwin()) {
    StringRef newArch = getArchForAppleTargetSpecificModuleTriple(triple);

    StringRef newVendor = getVendorForAppleTargetSpecificModuleTriple(triple);

    StringRef newOS = getOSForAppleTargetSpecificModuleTriple(triple);

    Optional<StringRef> newEnvironment =
        getEnvironmentForAppleTargetSpecificModuleTriple(triple);

    if (!newEnvironment)
      // Generate an arch-vendor-os triple.
      return llvm::Triple(newArch, newVendor, newOS);

    // Generate an arch-vendor-os-environment triple.
    return llvm::Triple(newArch, newVendor, newOS, *newEnvironment);
  }

  // android - drop the API level.  That is not pertinent to the module; the API
  // availability is handled by the clang importer.
  if (triple.isAndroid()) {
    StringRef environment =
        llvm::Triple::getEnvironmentTypeName(triple.getEnvironment());

    return llvm::Triple(triple.getArchName(), triple.getVendorName(),
                        triple.getOSName(), environment);
  }

  // Other platforms get no normalization.
  return triple;
}

Optional<llvm::VersionTuple>
swift::getSwiftRuntimeCompatibilityVersionForTarget(const llvm::Triple &Triple){
  unsigned Major, Minor, Micro;

  if (Triple.isMacOSX()) {
    Triple.getMacOSXVersion(Major, Minor, Micro);
    if (Major == 10) {
      if (Minor <= 14) {
        return llvm::VersionTuple(5, 0);
      } else if (Minor <= 15) {
        return llvm::VersionTuple(5, 1);
      } else {
        return None;
      }
    } else {
      return None;
    }
  } else if (Triple.isiOS()) { // includes tvOS
    Triple.getiOSVersion(Major, Minor, Micro);
    if (Major <= 12) {
      return llvm::VersionTuple(5, 0);
    } else if (Major <= 13) {
      return llvm::VersionTuple(5, 1);
    } else {
      return None;
    }
  } else if (Triple.isWatchOS()) {
    Triple.getWatchOSVersion(Major, Minor, Micro);
    if (Major <= 5) {
      return llvm::VersionTuple(5, 0);
    } else if (Major <= 6) {
      return llvm::VersionTuple(5, 1);
    } else {
      return None;
    }
  } else {
    return None;
  }
}

<commit_msg>Simplifying the flow (#28010)<commit_after>//===--- Platform.cpp - Implement platform-related helpers ----------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/Basic/Platform.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/VersionTuple.h"

using namespace swift;

bool swift::tripleIsiOSSimulator(const llvm::Triple &triple) {
  llvm::Triple::ArchType arch = triple.getArch();
  return (triple.isiOS() &&
          // FIXME: transitional, this should eventually stop testing arch, and
          // switch to only checking the -environment field.
          (triple.isSimulatorEnvironment() ||
           arch == llvm::Triple::x86 || arch == llvm::Triple::x86_64));
}

bool swift::tripleIsAppleTVSimulator(const llvm::Triple &triple) {
  llvm::Triple::ArchType arch = triple.getArch();
  return (triple.isTvOS() &&
          // FIXME: transitional, this should eventually stop testing arch, and
          // switch to only checking the -environment field.
          (triple.isSimulatorEnvironment() ||
           arch == llvm::Triple::x86 || arch == llvm::Triple::x86_64));
}

bool swift::tripleIsWatchSimulator(const llvm::Triple &triple) {
  llvm::Triple::ArchType arch = triple.getArch();
  return (triple.isWatchOS() &&
          // FIXME: transitional, this should eventually stop testing arch, and
          // switch to only checking the -environment field.
          (triple.isSimulatorEnvironment() ||
           arch == llvm::Triple::x86 || arch == llvm::Triple::x86_64));
}

bool swift::tripleIsAnySimulator(const llvm::Triple &triple) {
  // FIXME: transitional, this should eventually just use the -environment
  // field.
  return triple.isSimulatorEnvironment() ||
    tripleIsiOSSimulator(triple) ||
    tripleIsWatchSimulator(triple) ||
    tripleIsAppleTVSimulator(triple);
}

bool swift::tripleRequiresRPathForSwiftInOS(const llvm::Triple &triple) {
  if (triple.isMacOSX()) {
    // macOS 10.14.4 contains a copy of Swift, but the linker will still use an
    // rpath-based install name until 10.15.
    return triple.isMacOSXVersionLT(10, 15);
  }

  if (triple.isiOS()) {
    return triple.isOSVersionLT(12, 2);
  }

  if (triple.isWatchOS()) {
    return triple.isOSVersionLT(5, 2);
  }

  // Other platforms don't have Swift installed as part of the OS by default.
  return false;
}

DarwinPlatformKind swift::getDarwinPlatformKind(const llvm::Triple &triple) {
  if (triple.isiOS()) {
    if (triple.isTvOS()) {
      if (tripleIsAppleTVSimulator(triple))
        return DarwinPlatformKind::TvOSSimulator;
      return DarwinPlatformKind::TvOS;
    }

    if (tripleIsiOSSimulator(triple))
      return DarwinPlatformKind::IPhoneOSSimulator;
    return DarwinPlatformKind::IPhoneOS;
  }

  if (triple.isWatchOS()) {
    if (tripleIsWatchSimulator(triple))
      return DarwinPlatformKind::WatchOSSimulator;
    return DarwinPlatformKind::WatchOS;
  }

  if (triple.isMacOSX())
    return DarwinPlatformKind::MacOS;

  llvm_unreachable("Unsupported Darwin platform");
}

DarwinPlatformKind swift::getNonSimulatorPlatform(DarwinPlatformKind platform) {
  switch (platform) {
  case DarwinPlatformKind::MacOS:
    return DarwinPlatformKind::MacOS;
  case DarwinPlatformKind::IPhoneOS:
  case DarwinPlatformKind::IPhoneOSSimulator:
    return DarwinPlatformKind::IPhoneOS;
  case DarwinPlatformKind::TvOS:
  case DarwinPlatformKind::TvOSSimulator:
    return DarwinPlatformKind::TvOS;
  case DarwinPlatformKind::WatchOS:
  case DarwinPlatformKind::WatchOSSimulator:
    return DarwinPlatformKind::WatchOS;
  }
  llvm_unreachable("Unsupported Darwin platform");
}

static StringRef getPlatformNameForDarwin(const DarwinPlatformKind platform) {
  switch (platform) {
  case DarwinPlatformKind::MacOS:
    return "macosx";
  case DarwinPlatformKind::IPhoneOS:
    return "iphoneos";
  case DarwinPlatformKind::IPhoneOSSimulator:
    return "iphonesimulator";
  case DarwinPlatformKind::TvOS:
    return "appletvos";
  case DarwinPlatformKind::TvOSSimulator:
    return "appletvsimulator";
  case DarwinPlatformKind::WatchOS:
    return "watchos";
  case DarwinPlatformKind::WatchOSSimulator:
    return "watchsimulator";
  }
  llvm_unreachable("Unsupported Darwin platform");
}

StringRef swift::getPlatformNameForTriple(const llvm::Triple &triple) {
  switch (triple.getOS()) {
  case llvm::Triple::UnknownOS:
    llvm_unreachable("unknown OS");
  case llvm::Triple::Ananas:
  case llvm::Triple::CloudABI:
  case llvm::Triple::DragonFly:
  case llvm::Triple::Emscripten:
  case llvm::Triple::Fuchsia:
  case llvm::Triple::KFreeBSD:
  case llvm::Triple::Lv2:
  case llvm::Triple::NetBSD:
  case llvm::Triple::OpenBSD:
  case llvm::Triple::Solaris:
  case llvm::Triple::Minix:
  case llvm::Triple::RTEMS:
  case llvm::Triple::NaCl:
  case llvm::Triple::CNK:
  case llvm::Triple::AIX:
  case llvm::Triple::CUDA:
  case llvm::Triple::NVCL:
  case llvm::Triple::AMDHSA:
  case llvm::Triple::ELFIAMCU:
  case llvm::Triple::Mesa3D:
  case llvm::Triple::Contiki:
  case llvm::Triple::AMDPAL:
  case llvm::Triple::HermitCore:
  case llvm::Triple::Hurd:
  case llvm::Triple::WASI:
    return "";
  case llvm::Triple::Darwin:
  case llvm::Triple::MacOSX:
  case llvm::Triple::IOS:
  case llvm::Triple::TvOS:
  case llvm::Triple::WatchOS:
    return getPlatformNameForDarwin(getDarwinPlatformKind(triple));
  case llvm::Triple::Linux:
    return triple.isAndroid() ? "android" : "linux";
  case llvm::Triple::FreeBSD:
    return "freebsd";
  case llvm::Triple::Win32:
    switch (triple.getEnvironment()) {
    case llvm::Triple::Cygnus:
      return "cygwin";
    case llvm::Triple::GNU:
      return "mingw";
    case llvm::Triple::MSVC:
    case llvm::Triple::Itanium:
      return "windows";
    default:
      llvm_unreachable("unsupported Windows environment");
    }
  case llvm::Triple::PS4:
    return "ps4";
  case llvm::Triple::Haiku:
    return "haiku";
  }
  llvm_unreachable("unsupported OS");
}

StringRef swift::getMajorArchitectureName(const llvm::Triple &Triple) {
  if (Triple.isOSLinux()) {
    switch (Triple.getSubArch()) {
    case llvm::Triple::SubArchType::ARMSubArch_v7:
      return "armv7";
    case llvm::Triple::SubArchType::ARMSubArch_v6:
      return "armv6";
    default:
      break;
    }
  }
  return Triple.getArchName();
}

// The code below is responsible for normalizing target triples into the form
// used to name target-specific swiftmodule, swiftinterface, and swiftdoc files.
// If two triples have incompatible ABIs or can be distinguished by Swift #if
// declarations, they should normalize to different values.
//
// This code is only really used on platforms with toolchains supporting fat
// binaries (a single binary containing multiple architectures). On these
// platforms, this code should strip unnecessary details from target triple
// components and map synonyms to canonical values. Even values which don't need
// any special canonicalization should be documented here as comments.
//
// (Fallback behavior does not belong here; it should be implemented in code
// that calls this function, most importantly in SerializedModuleLoaderBase.)
//
// If you're trying to refer to this code to understand how Swift behaves and
// you're unfamiliar with LLVM internals, here's a cheat sheet for reading it:
//
// * llvm::Triple is the type for a target name. It's a bit of a misnomer,
//   because it can contain three or four values: arch-vendor-os[-environment].
//
// * In .Cases and .Case, the last argument is the value the arguments before it
//   map to. That is, `.Cases("bar", "baz", "foo")` will return "foo" if it sees
//   "bar" or "baz".
//
// * llvm::Optional is similar to a Swift Optional: it either contains a value
//   or represents the absence of one. `None` is equivalent to `nil`; leading
//   `*` is equivalent to trailing `!`; conversion to `bool` is a not-`None`
//   check.

static StringRef
getArchForAppleTargetSpecificModuleTriple(const llvm::Triple &triple) {
  auto tripleArchName = triple.getArchName();

  return llvm::StringSwitch<StringRef>(tripleArchName)
              .Cases("arm64", "aarch64", "arm64")
              .Cases("x86_64", "amd64", "x86_64")
              .Cases("i386", "i486", "i586", "i686", "i786", "i886", "i986",
                     "i386")
              .Cases("unknown", "", "unknown")
  // These values are also supported, but are handled by the default case below:
  //          .Case ("armv7s", "armv7s")
  //          .Case ("armv7k", "armv7k")
  //          .Case ("armv7", "armv7")
              .Default(tripleArchName);
}

static StringRef
getVendorForAppleTargetSpecificModuleTriple(const llvm::Triple &triple) {
  // We unconditionally normalize to "apple" because it's relatively common for
  // build systems to omit the vendor name or use an incorrect one like
  // "unknown". Most parts of the compiler ignore the vendor, so you might not
  // notice such a mistake.
  //
  // Please don't depend on this behavior--specify 'apple' if you're building
  // for an Apple platform.

  assert(triple.isOSDarwin() &&
         "shouldn't normalize non-Darwin triple to 'apple'");

  return "apple";
}

static StringRef
getOSForAppleTargetSpecificModuleTriple(const llvm::Triple &triple) {
  auto tripleOSName = triple.getOSName();

  // Truncate the OS name before the first digit. "Digit" here is ASCII '0'-'9'.
  auto tripleOSNameNoVersion = tripleOSName.take_until(llvm::isDigit);

  return llvm::StringSwitch<StringRef>(tripleOSNameNoVersion)
              .Cases("macos", "macosx", "darwin", "macos")
              .Cases("unknown", "", "unknown")
  // These values are also supported, but are handled by the default case below:
  //          .Case ("ios", "ios")
  //          .Case ("tvos", "tvos")
  //          .Case ("watchos", "watchos")
              .Default(tripleOSNameNoVersion);
}

static Optional<StringRef>
getEnvironmentForAppleTargetSpecificModuleTriple(const llvm::Triple &triple) {
  auto tripleEnvironment = triple.getEnvironmentName();

  // If the environment is empty, infer a "simulator" environment based on the
  // OS and architecture combination. This feature is deprecated and exists for
  // backwards compatibility only; build systems should pass the "simulator"
  // environment explicitly if they know they're building for a simulator.
  if (tripleEnvironment == "" && swift::tripleIsAnySimulator(triple))
    return StringRef("simulator");

  return llvm::StringSwitch<Optional<StringRef>>(tripleEnvironment)
              .Cases("unknown", "", None)
  // These values are also supported, but are handled by the default case below:
  //          .Case ("simulator", StringRef("simulator"))
              .Default(tripleEnvironment);
}

llvm::Triple swift::getTargetSpecificModuleTriple(const llvm::Triple &triple) {
  // isOSDarwin() returns true for all Darwin-style OSes, including macOS, iOS,
  // etc.
  if (triple.isOSDarwin()) {
    StringRef newArch = getArchForAppleTargetSpecificModuleTriple(triple);

    StringRef newVendor = getVendorForAppleTargetSpecificModuleTriple(triple);

    StringRef newOS = getOSForAppleTargetSpecificModuleTriple(triple);

    Optional<StringRef> newEnvironment =
        getEnvironmentForAppleTargetSpecificModuleTriple(triple);

    if (!newEnvironment)
      // Generate an arch-vendor-os triple.
      return llvm::Triple(newArch, newVendor, newOS);

    // Generate an arch-vendor-os-environment triple.
    return llvm::Triple(newArch, newVendor, newOS, *newEnvironment);
  }

  // android - drop the API level.  That is not pertinent to the module; the API
  // availability is handled by the clang importer.
  if (triple.isAndroid()) {
    StringRef environment =
        llvm::Triple::getEnvironmentTypeName(triple.getEnvironment());

    return llvm::Triple(triple.getArchName(), triple.getVendorName(),
                        triple.getOSName(), environment);
  }

  // Other platforms get no normalization.
  return triple;
}

Optional<llvm::VersionTuple>
swift::getSwiftRuntimeCompatibilityVersionForTarget(
    const llvm::Triple &Triple) {
  unsigned Major, Minor, Micro;

  if (Triple.isMacOSX()) {
    Triple.getMacOSXVersion(Major, Minor, Micro);
    if (Major == 10) {
      if (Minor <= 14) {
        return llvm::VersionTuple(5, 0);
      } else if (Minor <= 15) {
        return llvm::VersionTuple(5, 1);
      }
    }
  } else if (Triple.isiOS()) { // includes tvOS
    Triple.getiOSVersion(Major, Minor, Micro);
    if (Major <= 12) {
      return llvm::VersionTuple(5, 0);
    } else if (Major <= 13) {
      return llvm::VersionTuple(5, 1);
    }
  } else if (Triple.isWatchOS()) {
    Triple.getWatchOSVersion(Major, Minor, Micro);
    if (Major <= 5) {
      return llvm::VersionTuple(5, 0);
    } else if (Major <= 6) {
      return llvm::VersionTuple(5, 1);
    }
  }

  return None;
}
<|endoftext|>


<commit_before><commit_msg>fixed file allocation bug when existing files are larger than they're supposed to be<commit_after><|endoftext|>