<commit_before>/* The MIT License

   Copyright (c) 2013 Adrian Tan <atks@umich.edu>

   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 "variant_manip.h"

/**
 * Constructor.
 *
 * @ref_fasta_file reference sequence FASTA file.
 */
VariantManip::VariantManip(std::string ref_fasta_file)
{
    if (ref_fasta_file!="")
    {
        std::cerr << "atempting to load fai\n";

        fai = fai_load(ref_fasta_file.c_str());
        reference_present = fai!=NULL;
    }
};

/**
 * Constructor.
 */
VariantManip::VariantManip()
{
    reference_present = false;
}

/**
 * Converts VTYPE to string.
 */
std::string VariantManip::vtype2string(int32_t VTYPE)
{
    std::string s;

    if (!VTYPE)
    {
        s += (s.size()==0) ? "" : ";";
        s += "REF";
    }

    if (VTYPE & VT_SNP)
    {
        s += (s.size()==0) ? "" : ";";
        s += "SNP";
    }

    if (VTYPE & VT_MNP)
    {
        s += (s.size()==0) ? "" : ";";
        s += "MNP";
    }

    if (VTYPE & VT_INDEL)
    {
        s += (s.size()==0) ? "" : ";";
        s += "INDEL";
    }

    if (VTYPE & VT_CLUMPED)
    {
        s += (s.size()==0) ? "" : ";";
        s += "CLUMPED";
    }

    return s;
}

/**
 * Detects near by STRs.
 */
bool VariantManip::detect_str(const char* chrom, uint32_t pos1, Variant& variant)
{

    int32_t ref_len;
    //STR related
    char* ru = 0;
    ru = faidx_fetch_seq(fai, chrom, pos1, pos1, &ref_len);
    //std::cerr << "first ru: "<< ru << "\n";

    int32_t tract_len = 1;
    int32_t motif_len = 1;

    std::string motif = "";
    int32_t tlen = 0;

    while (1)
    {
        char* next_ru = 0;
        next_ru = faidx_fetch_seq(fai, chrom, pos1+tract_len*motif_len, pos1+(tract_len)*motif_len, &ref_len);

        //motif repeated
        if (strcmp(ru, next_ru)==0)
        {
            //extend tract length
            ++tract_len;
        }
        else //try longer motif
        {
            if (tract_len>1)
            {
                motif = std::string(ru);
                tlen = tract_len;
                free(next_ru);
                break;
            }

            //not STR
            if (motif_len>10)
            {
                free(next_ru);
                break;
            }

            free(ru);
            ++motif_len;
            tract_len=1;
            ru = faidx_fetch_seq(fai, chrom, pos1, pos1+motif_len-1, &ref_len);
        }

        free(next_ru);
    }

    free(ru);

    return true;
}

/**
 * Classifies variants.
 */
int32_t VariantManip::classify_variant(bcf_hdr_t *h, bcf1_t *v,  Variant& variant)
{
    return classify_variant(bcf_get_chrom(h, v), bcf_get_pos1(v), bcf_get_allele(v), bcf_get_n_allele(v), variant);
}

/**
 * Classifies variants.
 */
int32_t VariantManip::classify_variant(bcf_hdr_t *h, bcf1_t *v)
{
    Variant variant;
    return classify_variant(bcf_get_chrom(h, v), bcf_get_pos1(v), bcf_get_allele(v), bcf_get_n_allele(v), variant);
}

/**
 * Classifies variants.
 */
int32_t VariantManip::classify_variant(const char* chrom, uint32_t pos1, char** allele, int32_t n_allele)
{
    Variant variant;
    return classify_variant(chrom, pos1, allele, n_allele, variant);
}

/**
 * Classifies variants.
 */
int32_t VariantManip::classify_variant(const char* chrom, uint32_t pos1, char** allele, int32_t n_allele, Variant& v)
{
    int32_t pos0 = pos1-1;
    v.clear();

    int32_t rlen = strlen(allele[0]);

    for (uint32_t i=1; i<n_allele; ++i)
    {
        int32_t type = 0;
        int32_t alen = strlen(allele[i]);
        int32_t min_len = std::min(rlen, alen);
        int32_t dlen = alen-rlen;
        int32_t diff = 0;

        for (int32_t j=0; j<min_len; ++j)
        {
            if (allele[0][j]!=allele[i][j])
            {
                ++diff;
            }
        }

        //substitution variants
        if (min_len==diff)
        {
            type |= min_len==1 ? VT_SNP : VT_MNP;
        }

        //indel variants
        if (dlen)
        {
            type |= VT_INDEL;
        }

        //clumped SNPs and MNPs
        if (diff && diff < min_len)
        {
            type |= VT_CLUMPED;
        }

        v.type |= type;
        v.alleles.push_back(Allele(type, diff, alen, dlen, 0));
    }

    return v.type;
}

/**
 * Left trims a variant with unnecesary nucleotides.
 */
void VariantManip::left_trim(std::vector<std::string>& alleles, uint32_t& pos1, uint32_t& left_trimmed)
{
    bool may_left_trim =  true;

    for (uint32_t i=0; i<alleles.size(); ++i)
    {
        if (alleles[i].size()==1 || alleles[i].at(0)!=alleles[0].at(0))
        {
            may_left_trim = false;
            break;
        }
    }

    if (may_left_trim)
    {
        for (uint32_t i=0; i<alleles.size(); ++i)
        {
            alleles[i].erase(0, 1);
        }

        ++pos1;
        ++left_trimmed;
        return left_trim(alleles, pos1, left_trimmed);
    }
};

/**
 * Left aligns a variant.
 * @todo: rewrite input as char**
 */
void VariantManip::left_align(std::vector<std::string>& alleles, uint32_t& pos1, const char* chrom, uint32_t& left_aligned, uint32_t& right_trimmed)
{
    bool may_right_trim =  true;
    bool may_left_align = false;
    char lastBase = ' ';

    for (uint32_t i=0; i<alleles.size(); ++i)
    {
        if (!alleles[i].empty())
        {
            lastBase = (lastBase != ' ') ? lastBase : alleles[i].at(alleles[i].size()-1);
            if (lastBase != alleles[i].at(alleles[i].size()-1))
            {
                may_right_trim = false;
            }
        }
        else
        {
            may_left_align = true;
            may_right_trim = false;
            break;
        }
    }

    if(may_left_align)
    {
        std::string base = "";

        --pos1;

        int ref_len = 0;

        char *ref = faidx_fetch_seq(fai, chrom, pos1-1, pos1-1, &ref_len);
        base = std::string(ref);
        free(ref);

        for (uint32_t i=0; i<alleles.size(); ++i)
        {
            alleles[i].insert(0, 1, base.at(0));
        }

        ++left_aligned;
        return left_align(alleles, pos1, chrom, left_aligned, right_trimmed);
    }
    else if (may_right_trim)
    {
        for (uint32_t i=0; i<alleles.size(); ++i)
        {
            alleles[i].erase(alleles[i].size()-1);
        }

        ++right_trimmed;
        return left_align(alleles, pos1, chrom, left_aligned, right_trimmed);
    }
};

/**
 * Generates a probing haplotype with flanks around the variant of interest.
 * Flanks are equal length
 */
void VariantManip::generate_probes(const char* chrom,
                        int32_t pos1, uint32_t probeDiff, //
                        std::vector<std::string>& alleles, //store alleles
                        std::vector<std::string>& probes, //store probes
                        uint32_t min_flank_length,
                        int32_t& preambleLength) //store preamble length
{
    //map to usable number
    probes.resize(alleles.size(), "");

    //check allele lengths
    std::map<uint32_t, uint32_t> alleleLengths;
    for (uint32_t i=0; i<alleles.size(); ++i)
    {
       alleleLengths[alleles[i].size()]=1;
    }

    //for SNPs and MNPs and block substitutions
    if (alleleLengths.size()==1)
    {
        //just get flanking sequences
        //append preamble
        std::map<char, uint32_t> bases;
        std::string preamble;
        std::string postamble;
        char *base;
        uint32_t i = 1;
        int32_t ref_len;
        while (bases.size()<4 || preamble.size()<min_flank_length)
        {
            base = faidx_fetch_seq(fai, const_cast<char*>(chrom), pos1-1, pos1-1, &ref_len);
            preamble.append(1,base[0]);
            bases[base[0]] = 1;
            if (ref_len<1) free(base);
            ++i;
        }

        bases.clear();
        i=0;
        uint32_t alleleLength = alleles[0].size();
        while (bases.size()<4 || postamble.size()<min_flank_length)
        {
            base = faidx_fetch_seq(fai, const_cast<char*>(chrom), pos1+alleleLength+i, pos1+alleleLength+i, &ref_len);
            postamble.append(1,base[0]);
            bases[base[0]] = 1;
            if (ref_len<1) free(base);
            ++i;
        }

        for (uint32_t i=0; i<alleles.size(); ++i)
        {
            probes[i] = std::string(preamble.rbegin(), preamble.rend()).append(alleles[i]);
            probes[i] = probes[i].append(postamble);
        }

        preambleLength = preamble.size();
    }
    //for Indels and Complex Substitutions
    else
    {
        //find gald
        uint32_t min_len = alleles[0].size();
        uint32_t max_len = alleles[0].size();
        for (uint32_t i=1; i<alleles.size(); ++i)
        {
            if (alleles[i].size()<min_len)
                min_len = alleles[i].size();
            if (alleles[i].size()>max_len)
                max_len = alleles[i].size();
        }
        uint32_t gald = max_len-min_len;

        uint32_t currentDiff = 0;
        //current length of probe
        uint32_t length = 0;
        //number of point differences for each probe wrt the reference
        std::vector<uint32_t> diff(alleles.size(), 0);
        probes.resize(alleles.size(), "");

        generate_probes(chrom, pos1, min_flank_length, currentDiff, length, gald, diff, alleles, probes);

        //append preamble
        std::map<char, uint32_t> bases;
        std::string preamble;
        char* base;
        uint32_t i = 1;
        int32_t ref_len;
        while (bases.size()<4 || preamble.size()<min_flank_length)
        {
            base = faidx_fetch_seq(fai, const_cast<char*>(chrom), pos1+i-1, pos1+i-1, &ref_len);
            //myRefSeq->getString(base, chromNo, pos-i, 1);
            preamble.append(1,base[0]);
            bases[base[0]] = 1;
            ++i;
            if (base[0]=='N')
            {
                break;
            }
            if (ref_len<1) free(base);
        }

        preambleLength = preamble.size();

        for (uint32_t i=0; i<alleles.size(); ++i)
        {
            probes[i] = std::string(preamble.rbegin(), preamble.rend()).append(probes[i]);
        }
    }
}

/**
*Iteratively called function for generating a haplotype.
*/
void VariantManip::generate_probes(const char* chrom,
                        int32_t pos1,
                        uint32_t flankLength,
                        uint32_t& currentDiff,
                        uint32_t& length,
                        uint32_t gald,
                        std::vector<uint32_t>& diff,
                        std::vector<std::string>& alleles,
                        std::vector<std::string>& probes)
{
    //std::cerr << "B:" << currentDiff << " " << alleles.size()-1 << "\n";

    if (currentDiff<alleles.size() || length<=2*gald+flankLength)
    {
        std::map<std::string, uint32_t> probeHash;
        //extend probes
        for (uint32_t i=0; i<alleles.size(); ++i)
        {
//                if (i==0)
//                {
//                    std::string base;
//                    myRefSeq->getString(base, chromNo, (genomeIndex_t) (pos+length), 1);
//                    probes[0].append(1, base.at(0));
//                }
//                else
            {
                //copy from allele
                if (length<alleles[i].size())
                {
                    probes[i].append(1,alleles[i].at(length));
                }
                else//copy from reference
                {
                    int32_t start1 = (pos1+length-alleles[i].size()+alleles[0].size()-1);
                    int32_t ref_len;
                    char* base = faidx_fetch_seq(fai, const_cast<char*>(chrom), start1 , start1, &ref_len);
                    //myRefSeq->getString(base, chromNo, (genomeIndex_t) (pos+length-alleles[i].size()+alleles[0].size()), 1);
                    probes[i].append(1, base[0]);
                    if (ref_len<1) free(base);
                }
            }
            //std::cerr << probes[i] << "\n" ;
            probeHash[probes[i]] = 1;
        }

        currentDiff = probeHash.size();
        ++length;
        //std::cerr << probes[0] << "\n" << probes[1] << "\n";
        generate_probes(chrom, pos1, flankLength, currentDiff, length, gald, diff, alleles, probes);
    }
}<commit_msg>removed debug statements<commit_after>/* The MIT License

   Copyright (c) 2013 Adrian Tan <atks@umich.edu>

   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 "variant_manip.h"

/**
 * Constructor.
 *
 * @ref_fasta_file reference sequence FASTA file.
 */
VariantManip::VariantManip(std::string ref_fasta_file)
{
    if (ref_fasta_file!="")
    {
        fai = fai_load(ref_fasta_file.c_str());
        reference_present = fai!=NULL;
    }
};

/**
 * Constructor.
 */
VariantManip::VariantManip()
{
    reference_present = false;
}

/**
 * Converts VTYPE to string.
 */
std::string VariantManip::vtype2string(int32_t VTYPE)
{
    std::string s;

    if (!VTYPE)
    {
        s += (s.size()==0) ? "" : ";";
        s += "REF";
    }

    if (VTYPE & VT_SNP)
    {
        s += (s.size()==0) ? "" : ";";
        s += "SNP";
    }

    if (VTYPE & VT_MNP)
    {
        s += (s.size()==0) ? "" : ";";
        s += "MNP";
    }

    if (VTYPE & VT_INDEL)
    {
        s += (s.size()==0) ? "" : ";";
        s += "INDEL";
    }

    if (VTYPE & VT_CLUMPED)
    {
        s += (s.size()==0) ? "" : ";";
        s += "CLUMPED";
    }

    return s;
}

/**
 * Detects near by STRs.
 */
bool VariantManip::detect_str(const char* chrom, uint32_t pos1, Variant& variant)
{

    int32_t ref_len;
    //STR related
    char* ru = 0;
    ru = faidx_fetch_seq(fai, chrom, pos1, pos1, &ref_len);
    //std::cerr << "first ru: "<< ru << "\n";

    int32_t tract_len = 1;
    int32_t motif_len = 1;

    std::string motif = "";
    int32_t tlen = 0;

    while (1)
    {
        char* next_ru = 0;
        next_ru = faidx_fetch_seq(fai, chrom, pos1+tract_len*motif_len, pos1+(tract_len)*motif_len, &ref_len);

        //motif repeated
        if (strcmp(ru, next_ru)==0)
        {
            //extend tract length
            ++tract_len;
        }
        else //try longer motif
        {
            if (tract_len>1)
            {
                motif = std::string(ru);
                tlen = tract_len;
                free(next_ru);
                break;
            }

            //not STR
            if (motif_len>10)
            {
                free(next_ru);
                break;
            }

            free(ru);
            ++motif_len;
            tract_len=1;
            ru = faidx_fetch_seq(fai, chrom, pos1, pos1+motif_len-1, &ref_len);
        }

        free(next_ru);
    }

    free(ru);

    return true;
}

/**
 * Classifies variants.
 */
int32_t VariantManip::classify_variant(bcf_hdr_t *h, bcf1_t *v,  Variant& variant)
{
    return classify_variant(bcf_get_chrom(h, v), bcf_get_pos1(v), bcf_get_allele(v), bcf_get_n_allele(v), variant);
}

/**
 * Classifies variants.
 */
int32_t VariantManip::classify_variant(bcf_hdr_t *h, bcf1_t *v)
{
    Variant variant;
    return classify_variant(bcf_get_chrom(h, v), bcf_get_pos1(v), bcf_get_allele(v), bcf_get_n_allele(v), variant);
}

/**
 * Classifies variants.
 */
int32_t VariantManip::classify_variant(const char* chrom, uint32_t pos1, char** allele, int32_t n_allele)
{
    Variant variant;
    return classify_variant(chrom, pos1, allele, n_allele, variant);
}

/**
 * Classifies variants.
 */
int32_t VariantManip::classify_variant(const char* chrom, uint32_t pos1, char** allele, int32_t n_allele, Variant& v)
{
    int32_t pos0 = pos1-1;
    v.clear();

    int32_t rlen = strlen(allele[0]);

    for (uint32_t i=1; i<n_allele; ++i)
    {
        int32_t type = 0;
        int32_t alen = strlen(allele[i]);
        int32_t min_len = std::min(rlen, alen);
        int32_t dlen = alen-rlen;
        int32_t diff = 0;

        for (int32_t j=0; j<min_len; ++j)
        {
            if (allele[0][j]!=allele[i][j])
            {
                ++diff;
            }
        }

        //substitution variants
        if (min_len==diff)
        {
            type |= min_len==1 ? VT_SNP : VT_MNP;
        }

        //indel variants
        if (dlen)
        {
            type |= VT_INDEL;
        }

        //clumped SNPs and MNPs
        if (diff && diff < min_len)
        {
            type |= VT_CLUMPED;
        }

        v.type |= type;
        v.alleles.push_back(Allele(type, diff, alen, dlen, 0));
    }

    return v.type;
}

/**
 * Left trims a variant with unnecesary nucleotides.
 */
void VariantManip::left_trim(std::vector<std::string>& alleles, uint32_t& pos1, uint32_t& left_trimmed)
{
    bool may_left_trim =  true;

    for (uint32_t i=0; i<alleles.size(); ++i)
    {
        if (alleles[i].size()==1 || alleles[i].at(0)!=alleles[0].at(0))
        {
            may_left_trim = false;
            break;
        }
    }

    if (may_left_trim)
    {
        for (uint32_t i=0; i<alleles.size(); ++i)
        {
            alleles[i].erase(0, 1);
        }

        ++pos1;
        ++left_trimmed;
        return left_trim(alleles, pos1, left_trimmed);
    }
};

/**
 * Left aligns a variant.
 * @todo: rewrite input as char**
 */
void VariantManip::left_align(std::vector<std::string>& alleles, uint32_t& pos1, const char* chrom, uint32_t& left_aligned, uint32_t& right_trimmed)
{
    bool may_right_trim =  true;
    bool may_left_align = false;
    char lastBase = ' ';

    for (uint32_t i=0; i<alleles.size(); ++i)
    {
        if (!alleles[i].empty())
        {
            lastBase = (lastBase != ' ') ? lastBase : alleles[i].at(alleles[i].size()-1);
            if (lastBase != alleles[i].at(alleles[i].size()-1))
            {
                may_right_trim = false;
            }
        }
        else
        {
            may_left_align = true;
            may_right_trim = false;
            break;
        }
    }

    if(may_left_align)
    {
        std::string base = "";

        --pos1;

        int ref_len = 0;

        char *ref = faidx_fetch_seq(fai, chrom, pos1-1, pos1-1, &ref_len);
        base = std::string(ref);
        free(ref);

        for (uint32_t i=0; i<alleles.size(); ++i)
        {
            alleles[i].insert(0, 1, base.at(0));
        }

        ++left_aligned;
        return left_align(alleles, pos1, chrom, left_aligned, right_trimmed);
    }
    else if (may_right_trim)
    {
        for (uint32_t i=0; i<alleles.size(); ++i)
        {
            alleles[i].erase(alleles[i].size()-1);
        }

        ++right_trimmed;
        return left_align(alleles, pos1, chrom, left_aligned, right_trimmed);
    }
};

/**
 * Generates a probing haplotype with flanks around the variant of interest.
 * Flanks are equal length
 */
void VariantManip::generate_probes(const char* chrom,
                        int32_t pos1, uint32_t probeDiff, //
                        std::vector<std::string>& alleles, //store alleles
                        std::vector<std::string>& probes, //store probes
                        uint32_t min_flank_length,
                        int32_t& preambleLength) //store preamble length
{
    //map to usable number
    probes.resize(alleles.size(), "");

    //check allele lengths
    std::map<uint32_t, uint32_t> alleleLengths;
    for (uint32_t i=0; i<alleles.size(); ++i)
    {
       alleleLengths[alleles[i].size()]=1;
    }

    //for SNPs and MNPs and block substitutions
    if (alleleLengths.size()==1)
    {
        //just get flanking sequences
        //append preamble
        std::map<char, uint32_t> bases;
        std::string preamble;
        std::string postamble;
        char *base;
        uint32_t i = 1;
        int32_t ref_len;
        while (bases.size()<4 || preamble.size()<min_flank_length)
        {
            base = faidx_fetch_seq(fai, const_cast<char*>(chrom), pos1-1, pos1-1, &ref_len);
            preamble.append(1,base[0]);
            bases[base[0]] = 1;
            if (ref_len<1) free(base);
            ++i;
        }

        bases.clear();
        i=0;
        uint32_t alleleLength = alleles[0].size();
        while (bases.size()<4 || postamble.size()<min_flank_length)
        {
            base = faidx_fetch_seq(fai, const_cast<char*>(chrom), pos1+alleleLength+i, pos1+alleleLength+i, &ref_len);
            postamble.append(1,base[0]);
            bases[base[0]] = 1;
            if (ref_len<1) free(base);
            ++i;
        }

        for (uint32_t i=0; i<alleles.size(); ++i)
        {
            probes[i] = std::string(preamble.rbegin(), preamble.rend()).append(alleles[i]);
            probes[i] = probes[i].append(postamble);
        }

        preambleLength = preamble.size();
    }
    //for Indels and Complex Substitutions
    else
    {
        //find gald
        uint32_t min_len = alleles[0].size();
        uint32_t max_len = alleles[0].size();
        for (uint32_t i=1; i<alleles.size(); ++i)
        {
            if (alleles[i].size()<min_len)
                min_len = alleles[i].size();
            if (alleles[i].size()>max_len)
                max_len = alleles[i].size();
        }
        uint32_t gald = max_len-min_len;

        uint32_t currentDiff = 0;
        //current length of probe
        uint32_t length = 0;
        //number of point differences for each probe wrt the reference
        std::vector<uint32_t> diff(alleles.size(), 0);
        probes.resize(alleles.size(), "");

        generate_probes(chrom, pos1, min_flank_length, currentDiff, length, gald, diff, alleles, probes);

        //append preamble
        std::map<char, uint32_t> bases;
        std::string preamble;
        char* base;
        uint32_t i = 1;
        int32_t ref_len;
        while (bases.size()<4 || preamble.size()<min_flank_length)
        {
            base = faidx_fetch_seq(fai, const_cast<char*>(chrom), pos1+i-1, pos1+i-1, &ref_len);
            //myRefSeq->getString(base, chromNo, pos-i, 1);
            preamble.append(1,base[0]);
            bases[base[0]] = 1;
            ++i;
            if (base[0]=='N')
            {
                break;
            }
            if (ref_len<1) free(base);
        }

        preambleLength = preamble.size();

        for (uint32_t i=0; i<alleles.size(); ++i)
        {
            probes[i] = std::string(preamble.rbegin(), preamble.rend()).append(probes[i]);
        }
    }
}

/**
*Iteratively called function for generating a haplotype.
*/
void VariantManip::generate_probes(const char* chrom,
                        int32_t pos1,
                        uint32_t flankLength,
                        uint32_t& currentDiff,
                        uint32_t& length,
                        uint32_t gald,
                        std::vector<uint32_t>& diff,
                        std::vector<std::string>& alleles,
                        std::vector<std::string>& probes)
{
    //std::cerr << "B:" << currentDiff << " " << alleles.size()-1 << "\n";

    if (currentDiff<alleles.size() || length<=2*gald+flankLength)
    {
        std::map<std::string, uint32_t> probeHash;
        //extend probes
        for (uint32_t i=0; i<alleles.size(); ++i)
        {
//                if (i==0)
//                {
//                    std::string base;
//                    myRefSeq->getString(base, chromNo, (genomeIndex_t) (pos+length), 1);
//                    probes[0].append(1, base.at(0));
//                }
//                else
            {
                //copy from allele
                if (length<alleles[i].size())
                {
                    probes[i].append(1,alleles[i].at(length));
                }
                else//copy from reference
                {
                    int32_t start1 = (pos1+length-alleles[i].size()+alleles[0].size()-1);
                    int32_t ref_len;
                    char* base = faidx_fetch_seq(fai, const_cast<char*>(chrom), start1 , start1, &ref_len);
                    //myRefSeq->getString(base, chromNo, (genomeIndex_t) (pos+length-alleles[i].size()+alleles[0].size()), 1);
                    probes[i].append(1, base[0]);
                    if (ref_len<1) free(base);
                }
            }
            //std::cerr << probes[i] << "\n" ;
            probeHash[probes[i]] = 1;
        }

        currentDiff = probeHash.size();
        ++length;
        //std::cerr << probes[0] << "\n" << probes[1] << "\n";
        generate_probes(chrom, pos1, flankLength, currentDiff, length, gald, diff, alleles, probes);
    }
}<|endoftext|>


<commit_before>#pragma once
#include<string>
#include<cstdint>
#include<fstream>
#include<array>
#include<vector>
namespace bmslib {

	std::vector<std::string> split_naive(const std::string &s, char delim) {
		std::vector<std::string> elems;
		std::string item;
		for (char ch : s) {
			if (ch == delim) {
				if (!item.empty())
					elems.push_back(item);
				item.clear();
			}
			else {
				item += ch;
			}
		}
		if (!item.empty())
			elems.push_back(item);
		return elems;
	}

	enum Player {
		None,
		Single,
		Couple,
		Double,
		Battle
	};

	enum Rank {
		Veryhard,
		Hard,
		Normal,
		Easy
	};

	struct Header
	{
		Player player;
		std::string genre, title, artist, stagefile;
		double bpm;
		unsigned int level, volume, total;
		Rank rank;
		std::array<std::string, 575> wav, bmp;
	};

	enum Channel {
		None,
		Backwav,
		Shortening,
		Changebpm,
		Bga,
		None,
		Pooranim,
		Bgalayer,
		Changebpm,
		Stop,
		None,
		Key1,
		Key2,
		Key3,
		Key4,
		Key5,
		Key6,
		Key7,
		Key8,
		Key9,
		None,
		Key1_2P,
		Key2_2P,
		Key3_2P,
		Key4_2P,
		Key5_2P,
		Key6_2P,
		Key7_2P,
		Key8_2P,
		Key9_2P,
	};

	struct Bar {
		int backchorus; // Set WAV number
		int length = 1000; // Default Value = 1000
		std::vector<double> bpms;
		int bga, pooranim, layerbga;
		std::array<std::vector<bool>, 9> objects;
	};

	struct Bms {
		Header header;
		std::vector<Bar> bar;
		bool ok = false;
	};

	Bms load(std::string bmsfile) {
		std::ifstream file(bmsfile);
		std::string line;
		if (file.fail())
		{
			return Bms();
		}
		Bms bms;
		while (getline(file, line))
		{
			if (line[0] == '#') {
				if (isdigit(line[1])) {

				}
				else {
					auto strs = split_naive(line, ' ');
					std::string command = strs[0].substr(1);
					std::string arg1 = strs[1];
					if (!std::strcmp(command.c_str(), "PLAYER")) {
						bms.header.player = static_cast<Player>(std::stoi(arg1.c_str()));
					}
					if (!std::strcmp(command.c_str(), "GENRE")) {
						bms.header.genre = arg1;
					}
					if (!std::strcmp(command.c_str(), "TITLE")) {
						bms.header.title = arg1;
					}
					if (!std::strcmp(command.c_str(), "ARTIST")) {
						bms.header.artist = arg1;
					}
					if (!std::strcmp(command.c_str(), "BPM")) {
						bms.header.bpm = std::stof(arg1);
					}
					if (!std::strcmp(command.c_str(), "PLAYLEVEL")) {
						bms.header.level = std::stoi(arg1);
					}
					if (!std::strcmp(command.c_str(), "RANK")) {
						bms.header.rank = static_cast<Rank>(std::stoi(arg1));
					}
					if (!std::strcmp(command.c_str(), "VOLWAV")) {
						bms.header.volume = std::stoi(arg1);
					}
					if (!std::strcmp(command.c_str(), "TOTAL")) {
						bms.header.total = std::stoi(arg1);
					}
					if (!std::strcmp(command.substr(0,3).c_str(), "WAV")) {
						bms.header.wav[std::stoi(command.substr(3, 2), nullptr, 36)] = arg1;
					}
					if (!std::strcmp(command.substr(0, 3).c_str(), "BMP")) {
						bms.header.bmp[std::stoi(command.substr(3, 2), nullptr, 36)] = arg1;
					}
					if (!std::strcmp(command.c_str(), "StageFile")) {
						bms.header.stagefile = arg1;
					}
				}
			}
		}
	}

	void save(std::string filename, const Bms& bms) {

	}
}<commit_msg>divided load()<commit_after>#pragma once
#include<string>
#include<cstdint>
#include<fstream>
#include<array>
#include<vector>
namespace bmslib {

	std::vector<std::string> split_naive(const std::string &s, char delim) {
		std::vector<std::string> elems;
		std::string item;
		for (char ch : s) {
			if (ch == delim) {
				if (!item.empty())
					elems.push_back(item);
				item.clear();
			}
			else {
				item += ch;
			}
		}
		if (!item.empty())
			elems.push_back(item);
		return elems;
	}

	enum Player {
		None,
		Single,
		Couple,
		Double,
		Battle
	};

	enum Rank {
		Veryhard,
		Hard,
		Normal,
		Easy
	};

	struct Header
	{
		Player player;
		std::string genre, title, artist, stagefile;
		double bpm;
		unsigned int level, volume, total;
		Rank rank;
		std::array<std::string, 575> wav, bmp;
	};

	enum Channel {
		None,
		Backwav,
		Shortening,
		Changebpm,
		Bga,
		None,
		Pooranim,
		Bgalayer,
		Changebpm,
		Stop,
		None,
		Key1,
		Key2,
		Key3,
		Key4,
		Key5,
		Key6,
		Key7,
		Key8,
		Key9,
		None,
		Key1_2P,
		Key2_2P,
		Key3_2P,
		Key4_2P,
		Key5_2P,
		Key6_2P,
		Key7_2P,
		Key8_2P,
		Key9_2P,
	};

	struct Bar {
		Channel channel;
		int backchorus; // Set WAV number
		int length = 1000; // Default Value = 1000
		std::vector<double> bpms;
		int bga, pooranim, layerbga;
		std::array<std::vector<bool>, 9> objects;
	};

	struct Bms {
		Header header;
		std::vector<Bar> bar;
	};

	Bms load_data(std::string bmsfile) {
		std::ifstream file(bmsfile);
		std::string line;
		if (file.fail())
		{
			return Bms();
		}
		Bms bms;
		while (getline(file, line))
		{
			if (line[0] == '#') {
				if (isdigit(line[1])) {
					if (bms.bar.size() < std::stoi(line.substr(1, 3)) + 1){
						bms.bar.reserve(std::stoi(line.substr(1, 3)) + 1);
					}
					Bar bar;
					bar.channel = static_cast<Channel>(std::stoi(line.substr(4, 2)));

					bms.bar[std::stoi(line.substr(1, 3))];
				}
			}
		}
	}

	Bms loadheader(std::string bmsfile) {
		std::ifstream file(bmsfile);
		std::string line;
		if (file.fail())
		{
			return Bms();
		}
		Bms bms;
		while (getline(file, line))
		{
			if (line[0] == '#') {
				if (!isdigit(line[1])) {
					auto strs = split_naive(line, ' ');
					std::string command = strs[0].substr(1);
					std::string arg1 = strs[1];
					if (!std::strcmp(command.c_str(), "PLAYER")) {
						bms.header.player = static_cast<Player>(std::stoi(arg1.c_str()));
					}
					if (!std::strcmp(command.c_str(), "GENRE")) {
						bms.header.genre = arg1;
					}
					if (!std::strcmp(command.c_str(), "TITLE")) {
						bms.header.title = arg1;
					}
					if (!std::strcmp(command.c_str(), "ARTIST")) {
						bms.header.artist = arg1;
					}
					if (!std::strcmp(command.c_str(), "BPM")) {
						bms.header.bpm = std::stof(arg1);
					}
					if (!std::strcmp(command.c_str(), "PLAYLEVEL")) {
						bms.header.level = std::stoi(arg1);
					}
					if (!std::strcmp(command.c_str(), "RANK")) {
						bms.header.rank = static_cast<Rank>(std::stoi(arg1));
					}
					if (!std::strcmp(command.c_str(), "VOLWAV")) {
						bms.header.volume = std::stoi(arg1);
					}
					if (!std::strcmp(command.c_str(), "TOTAL")) {
						bms.header.total = std::stoi(arg1);
					}
					if (!std::strcmp(command.substr(0, 3).c_str(), "WAV")) {
						bms.header.wav[std::stoi(command.substr(3, 2), nullptr, 36)] = arg1;
					}
					if (!std::strcmp(command.substr(0, 3).c_str(), "BMP")) {
						bms.header.bmp[std::stoi(command.substr(3, 2), nullptr, 36)] = arg1;
					}
					if (!std::strcmp(command.c_str(), "StageFile")) {
						bms.header.stagefile = arg1;
					}
				}
			}
		}
	}

	void save(std::string filename, const Bms& bms) {

	}
}<|endoftext|>


<commit_before>// -----------------------------------------------------------------------------
//
// BSD 2-Clause License
//
// Copyright (c) 2017, sarah authors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------

#include <sarah/error_estimator.h>

namespace sarah
{

  namespace ErrorEstimator
  {

    template<int dim, int spacedim = dim, typename ValueType = double>
    void
    estimate (const dealii::FiniteElement<dim,spacedim> &finite_element,
	      const dealii::DoFHandler<dim,spacedim>    &dof_handler,
	      const dealii::Quadrature<dim>             &quadrature,
	      const dealii::PETScWrappers::MPI::Vector  &fe_function,
	      dealii::Vector<ValueType>                 &error_per_cell,
	      MPI_Comm                                  &mpi_communicator)
    {
      dealii::FEValues<dim> fe_values (finite_element, quadrature,
				       dealii::update_values            |
				       dealii::update_quadrature_points |
				       dealii::update_JxW_values);

      const unsigned int dofs_per_cell = finite_element.dofs_per_cell;
      const unsigned int n_q_points    = quadrature.size ();

      std::vector<dealii::types::global_dof_index> local_dof_indices (dofs_per_cell);

      std::vector<ValueType> function_values (n_q_points);

      // Let there be a cell identification number. This
      // identification has nothing to do with the internal
      // description of the cell, though it probably should.
      //
      // Perhaps there is a dealii::type::??? for this?
      unsigned int cell_id = 0;

      typename dealii::DoFHandler<dim>::active_cell_iterator
	cell = dof_handler.begin_active (),
	endc = dof_handler.end ();

      for (; cell!=endc; ++cell, ++cell_id)
	if (cell->subdomain_id () == dealii::Utilities::MPI::this_mpi_process (mpi_communicator))
	  {
	    fe_values.reinit (cell);

	    fe_values.get_function_values (fe_function, function_values);

	    const double cell_diameter = cell->diameter ();

	    for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
	      for (unsigned int j=0; j<dofs_per_cell; ++j)
		  {
		    // Integrate volume of the function in this cell.
		    error_per_cell (cell_id) +=
		      function_values[q_point]          *
		      fe_values.shape_value (j,q_point) *
		      fe_values.JxW (q_point) / cell_diameter;
		  }

	    // This should *never* happen, but sometimes it does....
	    error_per_cell (cell_id) = std::fabs (error_per_cell (cell_id));

	  } // cell!=endc
    }

    template<int dim, int spacedim = dim, typename ValueType = double>
    void
    estimate (const dealii::FiniteElement<dim,spacedim> &finite_element,
	      const dealii::DoFHandler<dim,spacedim>    &dof_handler,
	      const dealii::Quadrature<dim>             &quadrature,
	      const dealii::FunctionParser<dim>         &function_parser,
	      dealii::Vector<ValueType>                 &error_per_cell,
	      MPI_Comm                                  &mpi_communicator)
    {
      dealii::FEValues<dim> fe_values (finite_element, quadrature,
				       dealii::update_values            |
				       dealii::update_quadrature_points |
				       dealii::update_JxW_values);

      const unsigned int dofs_per_cell = finite_element.dofs_per_cell;
      const unsigned int n_q_points    = quadrature.size ();

      std::vector<dealii::types::global_dof_index> local_dof_indices (dofs_per_cell);

      std::vector<ValueType> function_values (n_q_points);

      // Let there be a cell identification number. This
      // identification has nothing to do with the internal
      // description of the cell, though it probably should.
      //
      // Perhaps there is a dealii::type::??? for this?
      unsigned int cell_id = 0;

      typename dealii::DoFHandler<dim>::active_cell_iterator
	cell = dof_handler.begin_active (),
	endc = dof_handler.end ();

      for (; cell!=endc; ++cell, ++cell_id)
	if (cell->subdomain_id () == dealii::Utilities::MPI::this_mpi_process (mpi_communicator))
	  {
	    fe_values.reinit (cell);

	    function_parser.value_list (fe_values.get_quadrature_points (),
					function_values);

	    for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
	      for (unsigned int j=0; j<dofs_per_cell; ++j)
		  {
		    // Integrate volume of the function in this cell.
		    error_per_cell (cell_id) +=
		      function_values[q_point]          *
		      fe_values.shape_value (j,q_point) *
		      fe_values.JxW (q_point);
		  }

	    // This should *never* happen, but sometimes it does....
	    error_per_cell (cell_id) = std::fabs (error_per_cell (cell_id));

	  } // cell!=endc
    }

  } // namepsace ErrorEstimator

} // namepsace sarah

#include "error_estimator.inst"

<commit_msg>Modify a comment.<commit_after>// -----------------------------------------------------------------------------
//
// BSD 2-Clause License
//
// Copyright (c) 2017, sarah authors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------

#include <sarah/error_estimator.h>

namespace sarah
{

  namespace ErrorEstimator
  {

    template<int dim, int spacedim = dim, typename ValueType = double>
    void
    estimate (const dealii::FiniteElement<dim,spacedim> &finite_element,
	      const dealii::DoFHandler<dim,spacedim>    &dof_handler,
	      const dealii::Quadrature<dim>             &quadrature,
	      const dealii::PETScWrappers::MPI::Vector  &fe_function,
	      dealii::Vector<ValueType>                 &error_per_cell,
	      MPI_Comm                                  &mpi_communicator)
    {
      dealii::FEValues<dim> fe_values (finite_element, quadrature,
				       dealii::update_values            |
				       dealii::update_quadrature_points |
				       dealii::update_JxW_values);

      const unsigned int dofs_per_cell = finite_element.dofs_per_cell;
      const unsigned int n_q_points    = quadrature.size ();

      std::vector<dealii::types::global_dof_index> local_dof_indices (dofs_per_cell);

      std::vector<ValueType> function_values (n_q_points);

      // Let there be a cell identification number. This
      // identification has nothing to do with the internal
      // description of the cell.
      unsigned int cell_id = 0;

      typename dealii::DoFHandler<dim>::active_cell_iterator
	cell = dof_handler.begin_active (),
	endc = dof_handler.end ();

      for (; cell!=endc; ++cell, ++cell_id)
	if (cell->subdomain_id () == dealii::Utilities::MPI::this_mpi_process (mpi_communicator))
	  {
	    fe_values.reinit (cell);

	    fe_values.get_function_values (fe_function, function_values);

	    const double cell_diameter = cell->diameter ();

	    for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
	      for (unsigned int j=0; j<dofs_per_cell; ++j)
		  {
		    // Integrate volume of the function in this cell.
		    error_per_cell (cell_id) +=
		      function_values[q_point]          *
		      fe_values.shape_value (j,q_point) *
		      fe_values.JxW (q_point) / cell_diameter;
		 }

	    // This should *never* happen, but sometimes it does....
	    error_per_cell (cell_id) = std::fabs (error_per_cell (cell_id));

	  } // cell!=endc
    }

    template<int dim, int spacedim = dim, typename ValueType = double>
    void
    estimate (const dealii::FiniteElement<dim,spacedim> &finite_element,
	      const dealii::DoFHandler<dim,spacedim>    &dof_handler,
	      const dealii::Quadrature<dim>             &quadrature,
	      const dealii::FunctionParser<dim>         &function_parser,
	      dealii::Vector<ValueType>                 &error_per_cell,
	      MPI_Comm                                  &mpi_communicator)
    {
      dealii::FEValues<dim> fe_values (finite_element, quadrature,
				       dealii::update_values            |
				       dealii::update_quadrature_points |
				       dealii::update_JxW_values);

      const unsigned int dofs_per_cell = finite_element.dofs_per_cell;
      const unsigned int n_q_points    = quadrature.size ();

      std::vector<dealii::types::global_dof_index> local_dof_indices (dofs_per_cell);

      std::vector<ValueType> function_values (n_q_points);

      // Let there be a cell identification number. This
      // identification has nothing to do with the internal
      // description of the cell, though it probably should.
      //
      // Perhaps there is a dealii::type::??? for this?
      unsigned int cell_id = 0;

      typename dealii::DoFHandler<dim>::active_cell_iterator
	cell = dof_handler.begin_active (),
	endc = dof_handler.end ();

      for (; cell!=endc; ++cell, ++cell_id)
	if (cell->subdomain_id () == dealii::Utilities::MPI::this_mpi_process (mpi_communicator))
	  {
	    fe_values.reinit (cell);

	    function_parser.value_list (fe_values.get_quadrature_points (),
					function_values);

	    for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
	      for (unsigned int j=0; j<dofs_per_cell; ++j)
		  {
		    // Integrate volume of the function in this cell.
		    error_per_cell (cell_id) +=
		      function_values[q_point]          *
		      fe_values.shape_value (j,q_point) *
		      fe_values.JxW (q_point);
		  }

	    // This should *never* happen, but sometimes it does....
	    error_per_cell (cell_id) = std::fabs (error_per_cell (cell_id));

	  } // cell!=endc
    }

  } // namepsace ErrorEstimator

} // namepsace sarah

#include "error_estimator.inst"

<|endoftext|>


<commit_before>//
// Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//

//
// bench.cpp : spdlog benchmarks
//
#include "spdlog/async.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/null_sink.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/sinks/simple_file_sink.h"
#include "spdlog/spdlog.h"

#include "utils.h"
#include <atomic>
#include <cstdlib> // EXIT_FAILURE
#include <iostream>
#include <memory>
#include <string>
#include <thread>

using namespace std;
using namespace std::chrono;
using namespace spdlog;
using namespace spdlog::sinks;
using namespace utils;

void bench(int howmany, std::shared_ptr<spdlog::logger> log);
void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count);

int main(int argc, char *argv[])
{

    int queue_size = 1048576;
    int howmany = 1000000;
    int threads = 10;
    int file_size = 30 * 1024 * 1024;
    int rotating_files = 5;

    try
    {

        if (argc > 1)
            howmany = atoi(argv[1]);
        if (argc > 2)
            threads = atoi(argv[2]);
        if (argc > 3)
            queue_size = atoi(argv[3]);

        cout << "*******************************************************************************\n";
        cout << "Single thread, " << format(howmany) << " iterations" << endl;
        cout << "*******************************************************************************\n";

        auto rotating_st = spdlog::rotating_logger_st("rotating_st", "logs/rotating_st.log", file_size, rotating_files);
        bench(howmany, rotating_st);
        auto daily_st = spdlog::daily_logger_st("daily_st", "logs/daily_st.log");
        bench(howmany, daily_st);
        bench(howmany, spdlog::create<null_sink_st>("null_st"));

        cout << "\n*******************************************************************************\n";
        cout << threads << " threads sharing same logger, " << format(howmany) << " iterations" << endl;
        cout << "*******************************************************************************\n";

        auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs/rotating_mt.log", file_size, rotating_files);
        bench_mt(howmany, rotating_mt, threads);

        auto daily_mt = spdlog::daily_logger_mt("daily_mt", "logs/daily_mt.log");
        bench_mt(howmany, daily_mt, threads);
        bench(howmany, spdlog::create<null_sink_st>("null_mt"));

        cout << "\n*******************************************************************************\n";
        cout << "async logging.. " << threads << " threads sharing same logger, " << format(howmany) << " iterations " << endl;
        cout << "*******************************************************************************\n";

        spdlog::init_thread_pool(queue_size, 1);
        for (int i = 0; i < 3; ++i)
        {
            auto as = spdlog::basic_logger_mt<spdlog::create_async>("as", "logs/basic_async.log", true);
            bench_mt(howmany, as, threads);
            spdlog::drop("as");
            spdlog::thread_pool()->wait_empty();
        }
    }
    catch (std::exception &ex)
    {
        std::cerr << "Error: " << ex.what() << std::endl;
        perror("Last error");
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

void bench(int howmany, std::shared_ptr<spdlog::logger> log)
{
    cout << log->name() << "...\t\t" << flush;
    auto start = system_clock::now();
    for (auto i = 0; i < howmany; ++i)
    {
        log->info("Hello logger: msg number {}", i);
    }

    auto delta = system_clock::now() - start;
    auto delta_d = duration_cast<duration<double>>(delta).count();
    cout << format(int(howmany / delta_d)) << "/sec" << endl;
}

void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count)
{

    cout << log->name() << "...\t\t" << flush;
    std::atomic<int> msg_counter{0};
    vector<thread> threads;
    auto start = system_clock::now();
    for (int t = 0; t < thread_count; ++t)
    {
        threads.push_back(std::thread([&]() {
            for (;;)
            {
                int counter = ++msg_counter;
                if (counter > howmany)
                    break;
                log->info("Hello logger: msg number {}", counter);
            }
        }));
    }

    for (auto &t : threads)
    {
        t.join();
    };

    auto delta = system_clock::now() - start;
    auto delta_d = duration_cast<duration<double>>(delta).count();
    cout << format(int(howmany / delta_d)) << "/sec" << endl;
}
<commit_msg>bench<commit_after>//
// Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//

//
// bench.cpp : spdlog benchmarks
//
#include "spdlog/async.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/null_sink.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/sinks/simple_file_sink.h"
#include "spdlog/spdlog.h"

#include "utils.h"
#include <atomic>
#include <cstdlib> // EXIT_FAILURE
#include <iostream>
#include <memory>
#include <string>
#include <thread>

using namespace std;
using namespace std::chrono;
using namespace spdlog;
using namespace spdlog::sinks;
using namespace utils;

void bench(int howmany, std::shared_ptr<spdlog::logger> log);
void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count);

int main(int argc, char *argv[])
{

    int queue_size = 1048576;
    int howmany = 1000000;
    int threads = 10;
    int file_size = 30 * 1024 * 1024;
    int rotating_files = 5;

    try
    {

        if (argc > 1)
            howmany = atoi(argv[1]);
        if (argc > 2)
            threads = atoi(argv[2]);
        if (argc > 3)
            queue_size = atoi(argv[3]);

        cout << "*******************************************************************************\n";
        cout << "Single thread, " << format(howmany) << " iterations" << endl;
        cout << "*******************************************************************************\n";

        auto rotating_st = spdlog::rotating_logger_st("rotating_st", "logs/rotating_st.log", file_size, rotating_files);
        bench(howmany, rotating_st);
        auto daily_st = spdlog::daily_logger_st("daily_st", "logs/daily_st.log");
        bench(howmany, daily_st);
        bench(howmany, spdlog::create<null_sink_st>("null_st"));

        cout << "\n*******************************************************************************\n";
        cout << threads << " threads sharing same logger, " << format(howmany) << " iterations" << endl;
        cout << "*******************************************************************************\n";

        auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs/rotating_mt.log", file_size, rotating_files);
        bench_mt(howmany, rotating_mt, threads);

        auto daily_mt = spdlog::daily_logger_mt("daily_mt", "logs/daily_mt.log");
        bench_mt(howmany, daily_mt, threads);
        bench(howmany, spdlog::create<null_sink_st>("null_mt"));

        cout << "\n*******************************************************************************\n";
        cout << "async logging.. " << threads << " threads sharing same logger, " << format(howmany) << " iterations " << endl;
        cout << "*******************************************************************************\n";

        for (int i = 0; i < 3; ++i)
        {
			spdlog::init_thread_pool(queue_size, 1);
            auto as = spdlog::basic_logger_mt<spdlog::create_async>("as", "logs/basic_async.log", true);
            bench_mt(howmany, as, threads);
            spdlog::drop("as");

        }
    }
    catch (std::exception &ex)
    {
        std::cerr << "Error: " << ex.what() << std::endl;
        perror("Last error");
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

void bench(int howmany, std::shared_ptr<spdlog::logger> log)
{
    cout << log->name() << "...\t\t" << flush;
    auto start = system_clock::now();
    for (auto i = 0; i < howmany; ++i)
    {
        log->info("Hello logger: msg number {}", i);
    }

    auto delta = system_clock::now() - start;
    auto delta_d = duration_cast<duration<double>>(delta).count();
    cout << format(int(howmany / delta_d)) << "/sec" << endl;
}

void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count)
{

    cout << log->name() << "...\t\t" << flush;
    std::atomic<int> msg_counter{0};
    vector<thread> threads;
    auto start = system_clock::now();
    for (int t = 0; t < thread_count; ++t)
    {
        threads.push_back(std::thread([&]() {
            for (;;)
            {
                int counter = ++msg_counter;
                if (counter > howmany)
                    break;
                log->info("Hello logger: msg number {}", counter);
            }
        }));
    }

    for (auto &t : threads)
    {
        t.join();
    };

    auto delta = system_clock::now() - start;
    auto delta_d = duration_cast<duration<double>>(delta).count();
    cout << format(int(howmany / delta_d)) << "/sec" << endl;
}
<|endoftext|>


<commit_before>//============================================================================//
// File:          qcan_defs.hpp                                               //
// Description:   QCAN classes - Definitions                                  //
//                                                                            //
// Copyright (C) MicroControl GmbH & Co. KG                                   //
// 53844 Troisdorf - Germany                                                  //
// www.microcontrol.net                                                       //
//                                                                            //
//----------------------------------------------------------------------------//
// Redistribution and use in source and binary forms, with or without         //
// modification, are permitted provided that the following conditions         //
// are met:                                                                   //
// 1. Redistributions of source code must retain the above copyright          //
//    notice, this list of conditions, the following disclaimer and           //
//    the referenced file 'LICENSE'.                                          //
// 2. Redistributions in binary form must reproduce the above copyright       //
//    notice, this list of conditions and the following disclaimer in the     //
//    documentation and/or other materials provided with the distribution.    //
// 3. Neither the name of MicroControl nor the names of its contributors      //
//    may be used to endorse or promote products derived from this software   //
//    without specific prior written permission.                              //
//                                                                            //
// Provided that this notice is retained in full, this software may be        //
// distributed under the terms of the GNU Lesser General Public License       //
// ("LGPL") version 3 as distributed in the 'LICENSE' file.                   //
//                                                                            //
//============================================================================//

#ifndef QCAN_DEFS_HPP_
#define QCAN_DEFS_HPP_

//-----------------------------------------------------------------------------
/*!
** \file    qcan_defs.hpp
** \brief   Global QCan definitions
**
** This file ...
**
*/

/*----------------------------------------------------------------------------*\
** Definitions                                                                **
**                                                                            **
\*----------------------------------------------------------------------------*/

//-------------------------------------------------------------------
/*!
** \defgroup QCAN QCan definitions
**
**
*/

//-------------------------------------------------------------------
/*!
** \def     QCAN_TCP_DEFAULT_PORT
** \ingroup QCAN
** \brief   Default port for TCP server
**
** This symbol defines the default TCP port for the server.
*/
#define  QCAN_TCP_DEFAULT_PORT      55660

//-------------------------------------------------------------------
/*!
** \def     QCAN_TCP_SOCKET_MAX
** \ingroup QCAN
** \brief   Maximum number of TCP sockets
**
** This symbol defines the maximum number of sockets connected to
** the TCP server.
*/
#define  QCAN_TCP_SOCKET_MAX        16

//-------------------------------------------------------------------
/*!
** \def     QCAN_NETWORK_MAX
** \ingroup QCAN
** \brief   Maximum number of networks
**
** This symbol defines the maximum number of networks.
*/
#define  QCAN_NETWORK_MAX           8

//-------------------------------------------------------------------
/*!
** QCan namespace
**
*/
namespace QCan {

   enum CAN_Bitrate_e {

      /*!
      ** No bit-rate defined
      */
      eCAN_BITRATE_NONE = -1,

      /*!
      ** bit-rate 10 kBit/sec
      */
      eCAN_BITRATE_10K = 0,

      /*!
      ** bit-rate 20 kBit/sec
      */
      eCAN_BITRATE_20K,

      /*!
      ** bit-rate 50 kBit/sec
      */
      eCAN_BITRATE_50K,

      /*!
      ** bit-rate 100 kBit/sec
      */
      eCAN_BITRATE_100K,

      /*!
      ** bit-rate 125 kBit/sec
      */
      eCAN_BITRATE_125K,

      /*!
      ** bit-rate 250 kBit/sec
      */
      eCAN_BITRATE_250K,

      /*!
      ** bit-rate 500 kBit/sec
      */
      eCAN_BITRATE_500K,

      /*!
      ** bit-rate 800 kBit/sec
      */
      eCAN_BITRATE_800K,

      /*!
      ** bit-rate 1 MBit/sec
      */
      eCAN_BITRATE_1M,

      /*!
      ** Use automatic bit-rate detection
      */
      eCAN_BITRATE_AUTO
   };

   enum CAN_Channel_e {

      /*! CAN interface 1              */
      eCAN_CHANNEL_1 = 0,

      /*! CAN interface 2              */
      eCAN_CHANNEL_2,

      /*! CAN interface 3              */
      eCAN_CHANNEL_3,

      /*! CAN interface 4              */
      eCAN_CHANNEL_4,

      /*! CAN interface 5              */
      eCAN_CHANNEL_5,

      /*! CAN interface 6              */
      eCAN_CHANNEL_6,

      /*! CAN interface 7              */
      eCAN_CHANNEL_7,

      /*! CAN interface 8              */
      eCAN_CHANNEL_8
   };

   enum CAN_State_e {
      /*!
      ** CAN controller is in stopped mode
      */
      eCAN_STATE_STOPPED  = 0,

      /*!
      ** CAN controller is in Sleep mode
      */
      eCAN_STATE_SLEEPING,

      /*!
      ** CAN controller is error active
      */
      eCAN_STATE_BUS_ACTIVE,

      /*!
      ** CAN controller is active, warning level is reached
      */
      eCAN_STATE_BUS_WARN,

      /*!
      ** CAN controller is error passive
      */
      eCAN_STATE_BUS_PASSIVE,

      /*!
      ** CAN controller went into Bus Off
      */
      eCAN_STATE_BUS_OFF
   };

   enum CAN_Mode_e {
      /*!   Set controller in Stop mode (no reception / transmission possible)
      */
      eCAN_MODE_STOP = 0,

      /*!   Set controller into normal operation
      */
      eCAN_MODE_START,

      /*!   Set controller into listen-only mode
      */
      eCAN_MODE_LISTEN_ONLY,

      /*!   Set controller into Sleep mode
      */
      eCAN_MODE_SLEEP
   };
}

#endif // QCAN_DEFS_HPP_
<commit_msg>Add QCAN_IF_SUPPORT_xx definitions<commit_after>//============================================================================//
// File:          qcan_defs.hpp                                               //
// Description:   QCAN classes - Definitions                                  //
//                                                                            //
// Copyright (C) MicroControl GmbH & Co. KG                                   //
// 53844 Troisdorf - Germany                                                  //
// www.microcontrol.net                                                       //
//                                                                            //
//----------------------------------------------------------------------------//
// Redistribution and use in source and binary forms, with or without         //
// modification, are permitted provided that the following conditions         //
// are met:                                                                   //
// 1. Redistributions of source code must retain the above copyright          //
//    notice, this list of conditions, the following disclaimer and           //
//    the referenced file 'LICENSE'.                                          //
// 2. Redistributions in binary form must reproduce the above copyright       //
//    notice, this list of conditions and the following disclaimer in the     //
//    documentation and/or other materials provided with the distribution.    //
// 3. Neither the name of MicroControl nor the names of its contributors      //
//    may be used to endorse or promote products derived from this software   //
//    without specific prior written permission.                              //
//                                                                            //
// Provided that this notice is retained in full, this software may be        //
// distributed under the terms of the GNU Lesser General Public License       //
// ("LGPL") version 3 as distributed in the 'LICENSE' file.                   //
//                                                                            //
//============================================================================//

#ifndef QCAN_DEFS_HPP_
#define QCAN_DEFS_HPP_

//-----------------------------------------------------------------------------
/*!
** \file    qcan_defs.hpp
** \brief   Global QCan definitions
**
** This file ...
**
*/

/*----------------------------------------------------------------------------*\
** Definitions                                                                **
**                                                                            **
\*----------------------------------------------------------------------------*/

//-------------------------------------------------------------------
/*!
** \defgroup QCAN_NW QCan network definitions
**
**
*/

//-------------------------------------------------------------------
/*!
** \def     QCAN_TCP_DEFAULT_PORT
** \ingroup QCAN_NW
** \brief   Default port for TCP server
**
** This symbol defines the default TCP port for the server.
*/
#define  QCAN_TCP_DEFAULT_PORT      55660

//-------------------------------------------------------------------
/*!
** \def     QCAN_TCP_SOCKET_MAX
** \ingroup QCAN_NW
** \brief   Maximum number of TCP sockets
**
** This symbol defines the maximum number of sockets connected to
** the TCP server.
*/
#define  QCAN_TCP_SOCKET_MAX        16

//-------------------------------------------------------------------
/*!
** \def     QCAN_NETWORK_MAX
** \ingroup QCAN_NW
** \brief   Maximum number of networks
**
** This symbol defines the maximum number of networks.
*/
#define  QCAN_NETWORK_MAX           8

//-------------------------------------------------------------------
/*!
** \defgroup QCAN_IF QCan interface definitions
**
**
*/

//-------------------------------------------------------------------
/*!
** \def     QCAN_IF_SUPPORT_ERROR_FRAMES
** \ingroup QCAN_IF
** \brief   Support error frames
**
** The bit-mask value defines if error frames are supported by
** a CAN interface.
*/
#define  QCAN_IF_SUPPORT_ERROR_FRAMES     ((uint32_t) (0x00000001))

//-------------------------------------------------------------------
/*!
** \def     QCAN_IF_SUPPORT_LISTEN_ONLY
** \ingroup QCAN_IF
** \brief   Support listen-only mode
**
** The bit-mask value defines if the listen-only mode is supported by
** a CAN interface.
*/
#define  QCAN_IF_SUPPORT_LISTEN_ONLY      ((uint32_t) (0x00000002))

//-------------------------------------------------------------------
/*!
** \def     QCAN_IF_SUPPORT_CAN_FD
** \ingroup QCAN_IF
** \brief   Support CAN FD
**
** The bit-mask value defines if CAN FD is supported by
** a CAN interface.
*/
#define  QCAN_IF_SUPPORT_CAN_FD           ((uint32_t) (0x00000004))

//-------------------------------------------------------------------
/*!
** QCan namespace
**
*/
namespace QCan {

   enum CAN_Bitrate_e {

      /*!
      ** No bit-rate defined
      */
      eCAN_BITRATE_NONE = -1,

      /*!
      ** bit-rate 10 kBit/sec
      */
      eCAN_BITRATE_10K = 0,

      /*!
      ** bit-rate 20 kBit/sec
      */
      eCAN_BITRATE_20K,

      /*!
      ** bit-rate 50 kBit/sec
      */
      eCAN_BITRATE_50K,

      /*!
      ** bit-rate 100 kBit/sec
      */
      eCAN_BITRATE_100K,

      /*!
      ** bit-rate 125 kBit/sec
      */
      eCAN_BITRATE_125K,

      /*!
      ** bit-rate 250 kBit/sec
      */
      eCAN_BITRATE_250K,

      /*!
      ** bit-rate 500 kBit/sec
      */
      eCAN_BITRATE_500K,

      /*!
      ** bit-rate 800 kBit/sec
      */
      eCAN_BITRATE_800K,

      /*!
      ** bit-rate 1 MBit/sec
      */
      eCAN_BITRATE_1M,

      /*!
      ** Use automatic bit-rate detection
      */
      eCAN_BITRATE_AUTO
   };

   enum CAN_Channel_e {

      /*! CAN interface 1              */
      eCAN_CHANNEL_1 = 0,

      /*! CAN interface 2              */
      eCAN_CHANNEL_2,

      /*! CAN interface 3              */
      eCAN_CHANNEL_3,

      /*! CAN interface 4              */
      eCAN_CHANNEL_4,

      /*! CAN interface 5              */
      eCAN_CHANNEL_5,

      /*! CAN interface 6              */
      eCAN_CHANNEL_6,

      /*! CAN interface 7              */
      eCAN_CHANNEL_7,

      /*! CAN interface 8              */
      eCAN_CHANNEL_8
   };

   enum CAN_State_e {
      /*!
      ** CAN controller is in stopped mode
      */
      eCAN_STATE_STOPPED  = 0,

      /*!
      ** CAN controller is in Sleep mode
      */
      eCAN_STATE_SLEEPING,

      /*!
      ** CAN controller is error active
      */
      eCAN_STATE_BUS_ACTIVE,

      /*!
      ** CAN controller is active, warning level is reached
      */
      eCAN_STATE_BUS_WARN,

      /*!
      ** CAN controller is error passive
      */
      eCAN_STATE_BUS_PASSIVE,

      /*!
      ** CAN controller went into Bus Off
      */
      eCAN_STATE_BUS_OFF
   };

   enum CAN_Mode_e {
      /*!   Set controller in Stop mode (no reception / transmission possible)
      */
      eCAN_MODE_STOP = 0,

      /*!   Set controller into normal operation
      */
      eCAN_MODE_START,

      /*!   Set controller into listen-only mode
      */
      eCAN_MODE_LISTEN_ONLY,

      /*!   Set controller into Sleep mode
      */
      eCAN_MODE_SLEEP
   };
}

#endif // QCAN_DEFS_HPP_
<|endoftext|>


<commit_before>/*
Copyright (c) 2009-2012, Intel Corporation
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
    * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// written by Roman Dementiev
//

#include "cpucounters.h"
#include <iostream>
#include <algorithm>
#include <list>
#include <vector>
#include <sys/time.h>
#include <emmintrin.h>
#include <assert.h>

using std::cout;

inline double my_timestamp()
{
    struct timeval tp;
    gettimeofday(&tp, NULL);
    return double(tp.tv_sec) + tp.tv_usec / 1000000.;
}

struct T
{
    int key[1];
    int data[3];

    T() { }
    T(int a) { key[0] = a; }

    bool operator == (const T & k) const
    {
        return k.key[0] == key[0];
    }
};

template <class Y>
void write_intensive_task(Y * p, Y * e, int value)
{
    __m128i i = _mm_set_epi32(value, value, value, value);

#if 0
    while (p != e)
    {
        *p = value;
        ++p;
    }
#else
    while (p != e)
    {
        _mm_store_si128((__m128i *)p++, i);
    }
#endif
}

template <class Y>
void stream_write_task(Y * p, Y * e, int value)
{
    __m128i i = _mm_set_epi32(value, value, value, value);

    while (p != e)
    {
        _mm_stream_si128((__m128i *)p++, i);
    }
}

template <class Y>
void read_intensive_task(Y * p, Y * e, int value)
{
    std::find(p, e, -1);
}

int main(int argc, char * argv[])
{
    assert((argc > 1) && "Need operation type as parameter: 0 - read, 1 - write, 2 - streaming write ");
    int op = atoi(argv[1]);
    T * vector;
    int nelements = 13000000;
    vector = new T[nelements];

    int i = 0;

    cout << "Elements data size: " << sizeof(T) * nelements / 1024 << " KB\n";

    for ( ; i < nelements; ++i)
    {
        vector[i].key[0] = 10;
    }

    double before_ts, after_ts;

    while (1)
    {
        before_ts = my_timestamp();
        switch (op)
        {
        case 1:
            cout << "Writing memory\n";
            break;
        case 0:
            cout << "Reading memory\n";
            break;
        default:
            cout << "Streaming to memory\n";
        }

        int niter = 32;
        i = niter;
        int r = rand();
        while (i--)
        {
            switch (op)
            {
            case 1:
                write_intensive_task(vector, vector + nelements, r);
                break;
            case 0:
                read_intensive_task(vector, vector + nelements, r);
                break;
            default:
                stream_write_task(vector, vector + nelements, r);
            }

            after_ts = my_timestamp();
        }
        cout << "Bandwidth: " << (sizeof(T) * nelements * niter) / ((after_ts - before_ts) * 1024 * 1024) << " MByte/sec\n";
    }

    delete[] vector;

    return 0;
}
<commit_msg>Add required flushes<commit_after>/*
Copyright (c) 2009-2012, Intel Corporation
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
    * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// written by Roman Dementiev
//

#include "cpucounters.h"
#include <iostream>
#include <algorithm>
#include <list>
#include <vector>
#include <sys/time.h>
#include <emmintrin.h>
#include <assert.h>

using std::cout;

inline double my_timestamp()
{
    struct timeval tp;
    gettimeofday(&tp, NULL);
    return double(tp.tv_sec) + tp.tv_usec / 1000000.;
}

struct T
{
    int key[1];
    int data[3];

    T() { }
    T(int a) { key[0] = a; }

    bool operator == (const T & k) const
    {
        return k.key[0] == key[0];
    }
};

template <class Y>
void write_intensive_task(Y * p, Y * e, int value)
{
    __m128i i = _mm_set_epi32(value, value, value, value);

#if 0
    while (p != e)
    {
        *p = value;
        ++p;
    }
#else
    while (p != e)
    {
        _mm_store_si128((__m128i *)p++, i);
    }
#endif
}

template <class Y>
void stream_write_task(Y * p, Y * e, int value)
{
    __m128i i = _mm_set_epi32(value, value, value, value);

    while (p != e)
    {
        _mm_stream_si128((__m128i *)p++, i);
    }
}

template <class Y>
void read_intensive_task(Y * p, Y * e, int value)
{
    std::find(p, e, -1);
}

int main(int argc, char * argv[])
{
    assert((argc > 1) && "Need operation type as parameter: 0 - read, 1 - write, 2 - streaming write ");
    int op = atoi(argv[1]);
    T * vector;
    int nelements = 13000000;
    vector = new T[nelements];

    int i = 0;

    cout << "Elements data size: " << sizeof(T) * nelements / 1024 << " KB\n";

    for ( ; i < nelements; ++i)
    {
        vector[i].key[0] = 10;
    }

    double before_ts, after_ts;

    while (1)
    {
        before_ts = my_timestamp();
        switch (op)
        {
        case 1:
            cout << "Writing memory\n";
            break;
        case 0:
            cout << "Reading memory\n";
            break;
        default:
            cout << "Streaming to memory\n";
        }
        cout << std::flush;

        int niter = 32;
        i = niter;
        int r = rand();
        while (i--)
        {
            switch (op)
            {
            case 1:
                write_intensive_task(vector, vector + nelements, r);
                break;
            case 0:
                read_intensive_task(vector, vector + nelements, r);
                break;
            default:
                stream_write_task(vector, vector + nelements, r);
            }

            after_ts = my_timestamp();
        }
        cout << "Bandwidth: " << (sizeof(T) * nelements * niter) / ((after_ts - before_ts) * 1024 * 1024) << " MByte/sec\n" << std::flush;
    }

    delete[] vector;

    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2010-2020, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.

#include "gmsh.hpp"
#include "vtk.hpp"

namespace mfem
{

void GmshHOSegmentMapping(int order, int *map)
{
   map[0] = 0;
   map[order] = 1;
   for (int i=1; i<order; i++)
   {
      map[i] = i + 1;
   }
}

void GmshHOTriangleMapping(int order, int *map)
{
   int b[3];
   int o = 0;
   for (b[1]=0; b[1]<=order; ++b[1])
   {
      for (b[0]=0; b[0]<=order-b[1]; ++b[0])
      {
         b[2] = order - b[0] - b[1];
         int o_gmsh =  BarycentricToVTKTriangle(b, order);
         map[o] = o_gmsh;
         o++;
      }
   }
}

void GmshHOQuadrilateralMapping(int order, int *map)
{}

void GmshHOTetrahedronMapping(int order, int *map)
{}

void GmshHOHexahedronMapping(int order, int *map)
{}

void GmshHOWedgeMapping(int order, int *map)
{}

void GmshHOPyramidMapping(int order, int *map)
{}

} // namespace mfem
<commit_msg>Gmsh quadrilateral mapping (thanks @pazner!)<commit_after>// Copyright (c) 2010-2020, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.

#include "gmsh.hpp"
#include "vtk.hpp"

namespace mfem
{

int CartesianToGmshQuad(int idx_in[], int ref)
{
   int i = idx_in[0];
   int j = idx_in[1];
   // Do we lie on any of the edges
   bool ibdr = (i == 0 || i == ref);
   bool jbdr = (j == 0 || j == ref);
   if (ibdr && jbdr) // Vertex DOF
   {
      return (i ? (j ? 2 : 1) : (j ? 3 : 0));
   }
   int offset = 4;
   if (jbdr) // Edge DOF on j==0 or j==ref
   {
      return offset + (j ? 3*ref - 3 - i : i - 1);
   }
   else if (ibdr) // Edge DOF on i==0 or i==ref
   {
      return offset + (i ? ref - 1 + j - 1 : 4*ref - 4 - j);
   }
   else // Recursive numbering for interior
   {
      int idx_out[2];
      idx_out[0] = i-1;
      idx_out[1] = j-1;
      offset += 4 * (ref - 1);
      return offset + CartesianToGmshQuad(idx_out, ref-2);
   }
}

void GmshHOSegmentMapping(int order, int *map)
{
   map[0] = 0;
   map[order] = 1;
   for (int i=1; i<order; i++)
   {
      map[i] = i + 1;
   }
}

void GmshHOTriangleMapping(int order, int *map)
{
   int b[3];
   int o = 0;
   for (b[1]=0; b[1]<=order; ++b[1])
   {
      for (b[0]=0; b[0]<=order-b[1]; ++b[0])
      {
         b[2] = order - b[0] - b[1];
         int o_gmsh =  BarycentricToVTKTriangle(b, order);
         map[o] = o_gmsh;
         o++;
      }
   }
}

void GmshHOQuadrilateralMapping(int order, int *map)
{
   int b[2];
   int o = 0;
   for (b[1]=0; b[1]<=order; b[1]++)
   {
      for (b[0]=0; b[0]<=order; b[0]++)
      {
         int o_gmsh = CartesianToGmshQuad(b, order);
         map[o] = o_gmsh;
         o++;
      }
   }
}

void GmshHOTetrahedronMapping(int order, int *map)
{}

void GmshHOHexahedronMapping(int order, int *map)
{}

void GmshHOWedgeMapping(int order, int *map)
{}

void GmshHOPyramidMapping(int order, int *map)
{}

} // namespace mfem
<|endoftext|>