<commit_before>#include "ARMDisassembler.h"
#include "Utils.h"

using namespace Utils;

std::string ARMDisassembler::Disassemble(uint32_t addr, uint32_t instr) {
    Opcode opcode = Decode(instr);
    switch (opcode) {
        case Opcode::INVALID: {
            return "invalid";
        } break;
        case Opcode::UNDEFINED: {
            return "undefined";
        } break;

        case Opcode::ADC:
        case Opcode::ADD:
        case Opcode::AND:
        case Opcode::BIC:
        case Opcode::CMN:
        case Opcode::CMP:
        case Opcode::MOV:
        case Opcode::MVN:
        case Opcode::ORR:
        case Opcode::RSB:
        case Opcode::RSC:
        case Opcode::EOR:
        case Opcode::SBC:
        case Opcode::SUB:
        case Opcode::TEQ:
        case Opcode::TST: {
            return DisassembleALU(opcode, instr);
        } break;

        case Opcode::B:
        case Opcode::BL: {
            // return DisassembleBranch(addr, instr, opcode);
        } break;

        case Opcode::BKPT: {
            // return DisassembleBKPT(instr);
        } break;

        case Opcode::BLX: {
            // return DisassembleBLX(instr);
        } break;

        case Opcode::BX: {
            // return DisassembleBX(instr);
        } break;

        case Opcode::CDP: {
            return "cdp";
        } break;

        case Opcode::CLREX: {
            return "clrex";
        } break;

        case Opcode::CLZ: {
            // return DisassembleCLZ(instr);
        } break;

        case Opcode::LDC: {
            return "ldc";
        } break;

        case Opcode::LDM:
        case Opcode::STM: {
            // return DisassembleMemblock(opcode, insn);
        } break;

        case Opcode::LDR:
        case Opcode::LDRB:
        case Opcode::LDRBT:
        case Opcode::LDRT:
        case Opcode::STR:
        case Opcode::STRB:
        case Opcode::STRBT:
        case Opcode::STRT: {
            // return DisassembleMem(insn);
        } break;

        case Opcode::LDREX:
        case Opcode::LDREXB:
        case Opcode::LDREXD:
        case Opcode::LDREXH:
        case Opcode::STREX:
        case Opcode::STREXB:
        case Opcode::STREXD:
        case Opcode::STREXH: {
            // return DisassembleREX(opcode, insn);
        } break;

        case Opcode::LDRH:
        case Opcode::LDRSB:
        case Opcode::LDRSH:
        case Opcode::STRH: {
            // return DisassembleMemHalf(insn);
        } break;

        case Opcode::MCR:
        case Opcode::MRC: {
            // return DisassembleMCR(opcode, insn);
        } break;
        case Opcode::MLA: {
            // return DisassembleMLA(opcode, insn);
        } break;

        case Opcode::MRS: {
            // return DisassembleMRS(insn);
        } break;

        case Opcode::MSR: {
            // return DisassembleMSR(insn);
        } break;

        case Opcode::MUL: {
            // return DisassembleMUL(opcode, insn);
        } break;

        case Opcode::NOP:
        case Opcode::SEV:
        case Opcode::WFE:
        case Opcode::WFI:
        case Opcode::YIELD: {
            // return DisassembleNoOperands(opcode, insn);
        } break;

        case Opcode::PKH: {
            // return DisassemblePKH(insn);
        } break;

        case Opcode::PLD: {
            // return DisassemblePLD(insn);
        } break;

        case Opcode::QADD16:
        case Opcode::QADD8:
        case Opcode::QASX:
        case Opcode::QSAX:
        case Opcode::QSUB16:
        case Opcode::QSUB8:
        case Opcode::SADD16:
        case Opcode::SADD8:
        case Opcode::SASX:
        case Opcode::SHADD16:
        case Opcode::SHADD8:
        case Opcode::SHASX:
        case Opcode::SHSAX:
        case Opcode::SHSUB16:
        case Opcode::SHSUB8:
        case Opcode::SSAX:
        case Opcode::SSUB16:
        case Opcode::SSUB8:
        case Opcode::UADD16:
        case Opcode::UADD8:
        case Opcode::UASX:
        case Opcode::UHADD16:
        case Opcode::UHADD8:
        case Opcode::UHASX:
        case Opcode::UHSAX:
        case Opcode::UHSUB16:
        case Opcode::UHSUB8:
        case Opcode::UQADD16:
        case Opcode::UQADD8:
        case Opcode::UQASX:
        case Opcode::UQSAX:
        case Opcode::UQSUB16:
        case Opcode::UQSUB8:
        case Opcode::USAX:
        case Opcode::USUB16:
        case Opcode::USUB8: {
            // return DisassembleParallelAddSub(opcode, insn);
        } break;

        case Opcode::REV:
        case Opcode::REV16:
        case Opcode::REVSH: {
            // return DisassembleREV(opcode, insn);
        }break;

        case Opcode::SEL: {
            // return DisassembleSEL(insn);
        } break;

        case Opcode::SMLAD:
        case Opcode::SMLALD:
        case Opcode::SMLSD:
        case Opcode::SMLSLD:
        case Opcode::SMMLA:
        case Opcode::SMMLS:
        case Opcode::SMMUL:
        case Opcode::SMUAD:
        case Opcode::SMUSD:
        case Opcode::USAD8:
        case Opcode::USADA8: {
            // return DisassembleMediaMulDiv(opcode, insn);
        } break;

        case Opcode::SSAT:
        case Opcode::SSAT16:
        case Opcode::USAT:
        case Opcode::USAT16: {
            // return DisassembleSAT(opcode, insn);
        } break;

        case Opcode::STC: {
            return "stc";
        } break;

        case Opcode::SWI: {
            // return DisassembleSWI(insn);
        } break;

        case Opcode::SWP:
        case Opcode::SWPB: {
            // return DisassembleSWP(opcode, insn);
        } break;

        case Opcode::SXTAB:
        case Opcode::SXTAB16:
        case Opcode::SXTAH:
        case Opcode::SXTB:
        case Opcode::SXTB16:
        case Opcode::SXTH:
        case Opcode::UXTAB:
        case Opcode::UXTAB16:
        case Opcode::UXTAH:
        case Opcode::UXTB:
        case Opcode::UXTB16:
        case Opcode::UXTH: {
            // return DisassembleXT(opcode, insn);
        } break;

        case Opcode::UMLAL:
        case Opcode::UMULL:
        case Opcode::SMLAL:
        case Opcode::SMULL: {
            // return DisassembleUMLAL(opcode, insn);
        } break;
    }
    return "invalid";
}

std::string ARMDisassembler::DisassembleALU(Opcode opcode, uint32_t instr) {

    uint8_t condition = (instr >> 28) & 0xF;
    uint8_t op = (instr >> 24) & 0xF;
    uint8_t is_immed = (instr >> 25) & 0x1;
    uint8_t bit_s = (instr >> 20) & 0x1;
    uint8_t rn = (instr >> 16) & 0xF;
    uint8_t rd = (instr >> 12) & 0xF;
    uint8_t immed = instr & 0xFF;

    uint8_t flags = 0;

    int opval = (int)opcode;
    const char *opcode_name = opcode_names[opval];

    switch (opcode) {
        // comparison opcodes don't have a destination and dont use 'S' bit
        case Opcode::CMN:
        case Opcode::CMP:
        case Opcode::TEQ:
        case Opcode::TST: {
            flags = kNoDest | kNoSBit;
        } break;

        // mov opcodes don't use operand1
        case Opcode::MOV:
        case Opcode::MVN: {
            flags = kNoOperand1;
        } break;

        default: break;
    }

    // register strings
    std::string rn_str = "";
    std::string rd_str = "";
    // S bit string
    std::string sbit_str = "";

    if ((flags & kNoOperand1) == 0) {
        rn_str = FormatString("r%d", rn);
    }

    if ((flags & kNoDest) == 0) {
        rd_str = FormatString("r%d", rd);
    }

    if (bit_s && !(flags & kNoSBit)) {
        sbit_str = "s";
    }

    if (is_immed) {
        return FormatString("%s%s%s\t%s, %s#%u ; #0x%x",
                            opcode_name,
                            cond_names[condition],
                            sbit_str.data(),
                            rd_str.data(),
                            rn_str.data(),
                            immed,
                            immed);
    }

    uint8_t shift_is_reg = (instr >> 4) & 0x1;
    uint8_t rotation = (instr >> 8) & 0xF;
    uint8_t rm = (instr) & 0xF;
    uint8_t shift_type = (instr >> 5) & 0x3;
    uint8_t rs = (instr >> 8) & 0xF;
    uint8_t shift_amount = (instr >> 7) & 0x1F;
    uint32_t rot_val = immed;
    uint8_t rotate = rot_val << 0x1;

    rot_val = (rot_val >> rotate) | (rot_val << (32 - rotate));

    if (!shift_is_reg && shift_type == 0 && shift_amount ==0) {
        return FormatString("%s%s%s\t%s, %sr%d",
                            opcode_name,
                            cond_names[condition],
                            sbit_str.data(),
                            rd_str.data(),
                            rn_str.data(),
                            rm);
    }

    const char *shift_name = shift_names[shift_type];
    if (shift_is_reg) {
        return FormatString("%s%s%s\t%s, %sr%d, %s r%d",
                            opcode_name,
                            cond_names[condition],
                            sbit_str.data(),
                            rd_str.data(),
                            rn_str.data(),
                            rm,
                            shift_name,
                            rs);
    }

    if (shift_amount == 0) {
        if (shift_type == 3) {
            return FormatString("%s%s%s\t%s, %sr%d, RRX", opcode_name, cond_names[condition], sbit_str.data(), rd_str.data(), rn_str.data(), rm);
        }
        shift_amount = 32;
    }

    return FormatString("%s%s%s\t%s, %sr%d, %s #%u",
                        opcode_name,
                        cond_names[condition],
                        sbit_str.data(),
                        rd_str.data(),
                        rn_str.data(),
                        rm,
                        shift_name,
                        shift_amount);
}

Opcode ARMDisassembler::Decode(uint32_t instr) {
    return Opcode::MOV;
}
<commit_msg>start implementing decode routines<commit_after>#include "ARMDisassembler.h"
#include "Utils.h"

using namespace Utils;

std::string ARMDisassembler::Disassemble(uint32_t addr, uint32_t instr) {
    Opcode opcode = Decode(instr);
    switch (opcode) {
        case Opcode::INVALID: {
            return "invalid";
        } break;
        case Opcode::UNDEFINED: {
            return "undefined";
        } break;

        case Opcode::ADC:
        case Opcode::ADD:
        case Opcode::AND:
        case Opcode::BIC:
        case Opcode::CMN:
        case Opcode::CMP:
        case Opcode::MOV:
        case Opcode::MVN:
        case Opcode::ORR:
        case Opcode::RSB:
        case Opcode::RSC:
        case Opcode::EOR:
        case Opcode::SBC:
        case Opcode::SUB:
        case Opcode::TEQ:
        case Opcode::TST: {
            return DisassembleALU(opcode, instr);
        } break;

        case Opcode::B:
        case Opcode::BL: {
            // return DisassembleBranch(addr, instr, opcode);
        } break;

        case Opcode::BKPT: {
            // return DisassembleBKPT(instr);
        } break;

        case Opcode::BLX: {
            // return DisassembleBLX(instr);
        } break;

        case Opcode::BX: {
            // return DisassembleBX(instr);
        } break;

        case Opcode::CDP: {
            return "cdp";
        } break;

        case Opcode::CLREX: {
            return "clrex";
        } break;

        case Opcode::CLZ: {
            // return DisassembleCLZ(instr);
        } break;

        case Opcode::LDC: {
            return "ldc";
        } break;

        case Opcode::LDM:
        case Opcode::STM: {
            // return DisassembleMemblock(opcode, insn);
        } break;

        case Opcode::LDR:
        case Opcode::LDRB:
        case Opcode::LDRBT:
        case Opcode::LDRT:
        case Opcode::STR:
        case Opcode::STRB:
        case Opcode::STRBT:
        case Opcode::STRT: {
            // return DisassembleMem(insn);
        } break;

        case Opcode::LDREX:
        case Opcode::LDREXB:
        case Opcode::LDREXD:
        case Opcode::LDREXH:
        case Opcode::STREX:
        case Opcode::STREXB:
        case Opcode::STREXD:
        case Opcode::STREXH: {
            // return DisassembleREX(opcode, insn);
        } break;

        case Opcode::LDRH:
        case Opcode::LDRSB:
        case Opcode::LDRSH:
        case Opcode::STRH: {
            // return DisassembleMemHalf(insn);
        } break;

        case Opcode::MCR:
        case Opcode::MRC: {
            // return DisassembleMCR(opcode, insn);
        } break;
        case Opcode::MLA: {
            // return DisassembleMLA(opcode, insn);
        } break;

        case Opcode::MRS: {
            // return DisassembleMRS(insn);
        } break;

        case Opcode::MSR: {
            // return DisassembleMSR(insn);
        } break;

        case Opcode::MUL: {
            // return DisassembleMUL(opcode, insn);
        } break;

        case Opcode::NOP:
        case Opcode::SEV:
        case Opcode::WFE:
        case Opcode::WFI:
        case Opcode::YIELD: {
            // return DisassembleNoOperands(opcode, insn);
        } break;

        case Opcode::PKH: {
            // return DisassemblePKH(insn);
        } break;

        case Opcode::PLD: {
            // return DisassemblePLD(insn);
        } break;

        case Opcode::QADD16:
        case Opcode::QADD8:
        case Opcode::QASX:
        case Opcode::QSAX:
        case Opcode::QSUB16:
        case Opcode::QSUB8:
        case Opcode::SADD16:
        case Opcode::SADD8:
        case Opcode::SASX:
        case Opcode::SHADD16:
        case Opcode::SHADD8:
        case Opcode::SHASX:
        case Opcode::SHSAX:
        case Opcode::SHSUB16:
        case Opcode::SHSUB8:
        case Opcode::SSAX:
        case Opcode::SSUB16:
        case Opcode::SSUB8:
        case Opcode::UADD16:
        case Opcode::UADD8:
        case Opcode::UASX:
        case Opcode::UHADD16:
        case Opcode::UHADD8:
        case Opcode::UHASX:
        case Opcode::UHSAX:
        case Opcode::UHSUB16:
        case Opcode::UHSUB8:
        case Opcode::UQADD16:
        case Opcode::UQADD8:
        case Opcode::UQASX:
        case Opcode::UQSAX:
        case Opcode::UQSUB16:
        case Opcode::UQSUB8:
        case Opcode::USAX:
        case Opcode::USUB16:
        case Opcode::USUB8: {
            // return DisassembleParallelAddSub(opcode, insn);
        } break;

        case Opcode::REV:
        case Opcode::REV16:
        case Opcode::REVSH: {
            // return DisassembleREV(opcode, insn);
        }break;

        case Opcode::SEL: {
            // return DisassembleSEL(insn);
        } break;

        case Opcode::SMLAD:
        case Opcode::SMLALD:
        case Opcode::SMLSD:
        case Opcode::SMLSLD:
        case Opcode::SMMLA:
        case Opcode::SMMLS:
        case Opcode::SMMUL:
        case Opcode::SMUAD:
        case Opcode::SMUSD:
        case Opcode::USAD8:
        case Opcode::USADA8: {
            // return DisassembleMediaMulDiv(opcode, insn);
        } break;

        case Opcode::SSAT:
        case Opcode::SSAT16:
        case Opcode::USAT:
        case Opcode::USAT16: {
            // return DisassembleSAT(opcode, insn);
        } break;

        case Opcode::STC: {
            return "stc";
        } break;

        case Opcode::SWI: {
            // return DisassembleSWI(insn);
        } break;

        case Opcode::SWP:
        case Opcode::SWPB: {
            // return DisassembleSWP(opcode, insn);
        } break;

        case Opcode::SXTAB:
        case Opcode::SXTAB16:
        case Opcode::SXTAH:
        case Opcode::SXTB:
        case Opcode::SXTB16:
        case Opcode::SXTH:
        case Opcode::UXTAB:
        case Opcode::UXTAB16:
        case Opcode::UXTAH:
        case Opcode::UXTB:
        case Opcode::UXTB16:
        case Opcode::UXTH: {
            // return DisassembleXT(opcode, insn);
        } break;

        case Opcode::UMLAL:
        case Opcode::UMULL:
        case Opcode::SMLAL:
        case Opcode::SMULL: {
            // return DisassembleUMLAL(opcode, insn);
        } break;
    }
    return "invalid";
}

std::string ARMDisassembler::DisassembleALU(Opcode opcode, uint32_t instr) {

    uint8_t condition = (instr >> 28) & 0xF;
    uint8_t op = (instr >> 24) & 0xF;
    uint8_t is_immed = (instr >> 25) & 0x1;
    uint8_t bit_s = (instr >> 20) & 0x1;
    uint8_t rn = (instr >> 16) & 0xF;
    uint8_t rd = (instr >> 12) & 0xF;
    uint8_t immed = instr & 0xFF;

    uint8_t flags = 0;

    int opval = (int)opcode;
    const char *opcode_name = opcode_names[opval];

    switch (opcode) {
        // comparison opcodes don't have a destination and dont use 'S' bit
        case Opcode::CMN:
        case Opcode::CMP:
        case Opcode::TEQ:
        case Opcode::TST: {
            flags = kNoDest | kNoSBit;
        } break;

        // mov opcodes don't use operand1
        case Opcode::MOV:
        case Opcode::MVN: {
            flags = kNoOperand1;
        } break;

        default: break;
    }

    // register strings
    std::string rn_str = "";
    std::string rd_str = "";
    // S bit string
    std::string sbit_str = "";

    if ((flags & kNoOperand1) == 0) {
        rn_str = FormatString("r%d", rn);
    }

    if ((flags & kNoDest) == 0) {
        rd_str = FormatString("r%d", rd);
    }

    if (bit_s && !(flags & kNoSBit)) {
        sbit_str = "s";
    }

    if (is_immed) {
        return FormatString("%s%s%s\t%s, %s#%u ; #0x%x",
                            opcode_name,
                            cond_names[condition],
                            sbit_str.data(),
                            rd_str.data(),
                            rn_str.data(),
                            immed,
                            immed);
    }

    uint8_t shift_is_reg = (instr >> 4) & 0x1;
    uint8_t rotation = (instr >> 8) & 0xF;
    uint8_t rm = (instr) & 0xF;
    uint8_t shift_type = (instr >> 5) & 0x3;
    uint8_t rs = (instr >> 8) & 0xF;
    uint8_t shift_amount = (instr >> 7) & 0x1F;
    uint32_t rot_val = immed;
    uint8_t rotate = rot_val << 0x1;

    rot_val = (rot_val >> rotate) | (rot_val << (32 - rotate));

    if (!shift_is_reg && shift_type == 0 && shift_amount ==0) {
        return FormatString("%s%s%s\t%s, %sr%d",
                            opcode_name,
                            cond_names[condition],
                            sbit_str.data(),
                            rd_str.data(),
                            rn_str.data(),
                            rm);
    }

    const char *shift_name = shift_names[shift_type];
    if (shift_is_reg) {
        return FormatString("%s%s%s\t%s, %sr%d, %s r%d",
                            opcode_name,
                            cond_names[condition],
                            sbit_str.data(),
                            rd_str.data(),
                            rn_str.data(),
                            rm,
                            shift_name,
                            rs);
    }

    if (shift_amount == 0) {
        if (shift_type == 3) {
            return FormatString("%s%s%s\t%s, %sr%d, RRX", opcode_name, cond_names[condition], sbit_str.data(), rd_str.data(), rn_str.data(), rm);
        }
        shift_amount = 32;
    }

    return FormatString("%s%s%s\t%s, %sr%d, %s #%u",
                        opcode_name,
                        cond_names[condition],
                        sbit_str.data(),
                        rd_str.data(),
                        rn_str.data(),
                        rm,
                        shift_name,
                        shift_amount);
}

Opcode ARMDisassembler::Decode(uint32_t instr) {
    // first 2 bits of opcode 1
    uint32_t ophi = (instr >> 26) & 0x3;
    switch (ophi) {
        case 0x0: return Decode00(instr);
        case 0x1: return Decode01(instr);
        case 0x2: return Decode10(instr);
        case 0x3: return Decode11(instr);
    }
    return Opcode::INVALID;
}

Opcode ARMDisassembler::Decode00(uint32_t instr) {
    uint8_t bit25 = (instr >> 25) & 0x1; // low bit of op 1
    uint8_t bit4 = (instr >> 4) & 0x1; // op (2)

    if (bit25 == 0 && bit4 == 1) {
        // TODO:
    }
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright 2014-2015 David Simmons-Duffin.
// Distributed under the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include "SDP_Solver_Parameters.hxx"
#include "Block_Info.hxx"
#include "../Timers.hxx"

#include <El.hpp>

#include <boost/date_time/posix_time/posix_time.hpp>

Timers
solve(const Block_Info &block_info, const SDP_Solver_Parameters &parameters);

void write_timing(const boost::filesystem::path &checkpoint_out,
                  const Block_Info &block_info, const Timers &timers,
                  const bool &debug);

int main(int argc, char **argv)
{
  El::Environment env(argc, argv);

  try
    {
      SDP_Solver_Parameters parameters(argc, argv);
      if(!parameters.is_valid())
        {
          return 0;
        }

      El::gmp::SetPrecision(parameters.precision);
      if(parameters.verbosity >= Verbosity::regular && El::mpi::Rank() == 0)
        {
          std::cout << "SDPB started at "
                    << boost::posix_time::second_clock::local_time() << '\n'
                    << parameters << '\n';
        }

      Block_Info block_info(parameters.sdp_directory, parameters.checkpoint_in,
                            parameters.procs_per_node,
                            parameters.proc_granularity, parameters.verbosity);
      // Only generate a block_timings file if
      // 1) We are running in parallel
      // 2) We did not load a block_timings file
      // 3) We are not going to load a checkpoint.
      if(El::mpi::Size(El::mpi::COMM_WORLD) > 1
         && block_info.block_timings_filename.empty()
         && !exists(parameters.checkpoint_in
                    / ("checkpoint." + std::to_string(El::mpi::Rank()))))
        {
          if(parameters.verbosity >= Verbosity::regular
             && El::mpi::Rank() == 0)
            {
              std::cout << "Performing a timing run\n";
            }
          SDP_Solver_Parameters timing_parameters(parameters);
          timing_parameters.max_iterations = 2;
          timing_parameters.no_final_checkpoint = true;
          timing_parameters.checkpoint_interval
            = std::numeric_limits<size_t>::max();
          timing_parameters.verbosity = Verbosity::none;
          Timers timers(solve(block_info, timing_parameters));

          write_timing(timing_parameters.checkpoint_out, block_info, timers,
                       timing_parameters.verbosity >= Verbosity::debug);
          El::mpi::Barrier(El::mpi::COMM_WORLD);
          block_info
            = Block_Info(parameters.sdp_directory, parameters.checkpoint_out,
                         parameters.procs_per_node,
                         parameters.proc_granularity, parameters.verbosity);

          parameters.max_runtime -= timers.front().second.elapsed_seconds();
        }
      else if(!block_info.block_timings_filename.empty()
              && block_info.block_timings_filename
                   != (parameters.checkpoint_out / "block_timings"))
        {
          if(El::mpi::Rank() == 0)
            {
              create_directories(parameters.checkpoint_out);
              copy_file(block_info.block_timings_filename,
                        parameters.checkpoint_out / "block_timings");
            }
        }
      solve(block_info, parameters);
    }
  catch(std::exception &e)
    {
      El::ReportException(e);
      El::mpi::Abort(El::mpi::COMM_WORLD, 1);
    }
  catch(...)
    {
      El::mpi::Abort(El::mpi::COMM_WORLD, 1);
    }
}
<commit_msg>Fix checkpointing bug during timing run<commit_after>//=======================================================================
// Copyright 2014-2015 David Simmons-Duffin.
// Distributed under the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include "SDP_Solver_Parameters.hxx"
#include "Block_Info.hxx"
#include "../Timers.hxx"

#include <El.hpp>

#include <boost/date_time/posix_time/posix_time.hpp>

Timers
solve(const Block_Info &block_info, const SDP_Solver_Parameters &parameters);

void write_timing(const boost::filesystem::path &checkpoint_out,
                  const Block_Info &block_info, const Timers &timers,
                  const bool &debug);

int main(int argc, char **argv)
{
  El::Environment env(argc, argv);

  try
    {
      SDP_Solver_Parameters parameters(argc, argv);
      if(!parameters.is_valid())
        {
          return 0;
        }

      El::gmp::SetPrecision(parameters.precision);
      if(parameters.verbosity >= Verbosity::regular && El::mpi::Rank() == 0)
        {
          std::cout << "SDPB started at "
                    << boost::posix_time::second_clock::local_time() << '\n'
                    << parameters << '\n';
        }

      Block_Info block_info(parameters.sdp_directory, parameters.checkpoint_in,
                            parameters.procs_per_node,
                            parameters.proc_granularity, parameters.verbosity);
      // Only generate a block_timings file if
      // 1) We are running in parallel
      // 2) We did not load a block_timings file
      // 3) We are not going to load a checkpoint.
      if(El::mpi::Size(El::mpi::COMM_WORLD) > 1
         && block_info.block_timings_filename.empty()
         && !exists(parameters.checkpoint_in
                    / ("checkpoint." + std::to_string(El::mpi::Rank()))))
        {
          if(parameters.verbosity >= Verbosity::regular
             && El::mpi::Rank() == 0)
            {
              std::cout << "Performing a timing run\n";
            }
          SDP_Solver_Parameters timing_parameters(parameters);
          timing_parameters.max_iterations = 2;
          timing_parameters.no_final_checkpoint = true;
          timing_parameters.checkpoint_interval
            = std::numeric_limits<int64_t>::max();
          timing_parameters.verbosity = Verbosity::none;
          Timers timers(solve(block_info, timing_parameters));

          write_timing(timing_parameters.checkpoint_out, block_info, timers,
                       timing_parameters.verbosity >= Verbosity::debug);
          El::mpi::Barrier(El::mpi::COMM_WORLD);
          block_info
            = Block_Info(parameters.sdp_directory, parameters.checkpoint_out,
                         parameters.procs_per_node,
                         parameters.proc_granularity, parameters.verbosity);

          parameters.max_runtime -= timers.front().second.elapsed_seconds();
        }
      else if(!block_info.block_timings_filename.empty()
              && block_info.block_timings_filename
                   != (parameters.checkpoint_out / "block_timings"))
        {
          if(El::mpi::Rank() == 0)
            {
              create_directories(parameters.checkpoint_out);
              copy_file(block_info.block_timings_filename,
                        parameters.checkpoint_out / "block_timings");
            }
        }
      solve(block_info, parameters);
    }
  catch(std::exception &e)
    {
      El::ReportException(e);
      El::mpi::Abort(El::mpi::COMM_WORLD, 1);
    }
  catch(...)
    {
      El::mpi::Abort(El::mpi::COMM_WORLD, 1);
    }
}
<|endoftext|>


<commit_before>//===- IndVarSimplify.cpp - Induction Variable Elimination ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Guarantees that all loops with identifiable, linear, induction variables will
// be transformed to have a single, canonical, induction variable.  After this
// pass runs, it guarantees the the first PHI node of the header block in the
// loop is the canonical induction variable if there is one.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar.h"
#include "llvm/Constants.h"
#include "llvm/Type.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/InductionVariable.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Support/CFG.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/Utils/Local.h"
#include "Support/Debug.h"
#include "Support/Statistic.h"
using namespace llvm;

namespace {
  Statistic<> NumRemoved ("indvars", "Number of aux indvars removed");
  Statistic<> NumInserted("indvars", "Number of canonical indvars added");

  class IndVarSimplify : public FunctionPass {
    LoopInfo *Loops;
    TargetData *TD;
  public:
    virtual bool runOnFunction(Function &) {
      Loops = &getAnalysis<LoopInfo>();
      TD = &getAnalysis<TargetData>();

      // Induction Variables live in the header nodes of loops
      bool Changed = false;
      for (unsigned i = 0, e = Loops->getTopLevelLoops().size(); i != e; ++i)
        Changed |= runOnLoop(Loops->getTopLevelLoops()[i]);
      return Changed;
    }

    unsigned getTypeSize(const Type *Ty) {
      if (unsigned Size = Ty->getPrimitiveSize())
        return Size;
      return TD->getTypeSize(Ty);  // Must be a pointer
    }

    bool runOnLoop(Loop *L);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<TargetData>();   // Need pointer size
      AU.addRequired<LoopInfo>();
      AU.addRequiredID(LoopSimplifyID);
      AU.addPreservedID(LoopSimplifyID);
      AU.setPreservesCFG();
    }
  };
  RegisterOpt<IndVarSimplify> X("indvars", "Canonicalize Induction Variables");
}

Pass *llvm::createIndVarSimplifyPass() {
  return new IndVarSimplify();
}

bool IndVarSimplify::runOnLoop(Loop *Loop) {
  // Transform all subloops before this loop...
  bool Changed = false;
  for (unsigned i = 0, e = Loop->getSubLoops().size(); i != e; ++i)
    Changed |= runOnLoop(Loop->getSubLoops()[i]);

  // Get the header node for this loop.  All of the phi nodes that could be
  // induction variables must live in this basic block.
  //
  BasicBlock *Header = Loop->getHeader();

  // Loop over all of the PHI nodes in the basic block, calculating the
  // induction variables that they represent... stuffing the induction variable
  // info into a vector...
  //
  std::vector<InductionVariable> IndVars;    // Induction variables for block
  BasicBlock::iterator AfterPHIIt = Header->begin();
  for (; PHINode *PN = dyn_cast<PHINode>(AfterPHIIt); ++AfterPHIIt)
    IndVars.push_back(InductionVariable(PN, Loops));
  // AfterPHIIt now points to first non-phi instruction...

  // If there are no phi nodes in this basic block, there can't be indvars...
  if (IndVars.empty()) return Changed;

  // Loop over the induction variables, looking for a canonical induction
  // variable, and checking to make sure they are not all unknown induction
  // variables.  Keep track of the largest integer size of the induction
  // variable.
  //
  InductionVariable *Canonical = 0;
  unsigned MaxSize = 0;

  for (unsigned i = 0; i != IndVars.size(); ++i) {
    InductionVariable &IV = IndVars[i];

    if (IV.InductionType != InductionVariable::Unknown) {
      unsigned IVSize = getTypeSize(IV.Phi->getType());

      if (IV.InductionType == InductionVariable::Canonical &&
          !isa<PointerType>(IV.Phi->getType()) && IVSize >= MaxSize)
        Canonical = &IV;

      if (IVSize > MaxSize) MaxSize = IVSize;

      // If this variable is larger than the currently identified canonical
      // indvar, the canonical indvar is not usable.
      if (Canonical && IVSize > getTypeSize(Canonical->Phi->getType()))
        Canonical = 0;
    }
  }

  // No induction variables, bail early... don't add a canonical indvar
  if (MaxSize == 0) return Changed;

  // Okay, we want to convert other induction variables to use a canonical
  // indvar.  If we don't have one, add one now...
  if (!Canonical) {
    // Create the PHI node for the new induction variable, and insert the phi
    // node at the start of the PHI nodes...
    const Type *IVType;
    switch (MaxSize) {
    default: assert(0 && "Unknown integer type size!");
    case 1: IVType = Type::UByteTy; break;
    case 2: IVType = Type::UShortTy; break;
    case 4: IVType = Type::UIntTy; break;
    case 8: IVType = Type::ULongTy; break;
    }

    PHINode *PN = new PHINode(IVType, "cann-indvar", Header->begin());

    // Create the increment instruction to add one to the counter...
    Instruction *Add = BinaryOperator::create(Instruction::Add, PN,
                                              ConstantUInt::get(IVType, 1),
                                              "next-indvar", AfterPHIIt);

    // Figure out which block is incoming and which is the backedge for the loop
    BasicBlock *Incoming, *BackEdgeBlock;
    pred_iterator PI = pred_begin(Header);
    assert(PI != pred_end(Header) && "Loop headers should have 2 preds!");
    if (Loop->contains(*PI)) {  // First pred is back edge...
      BackEdgeBlock = *PI++;
      Incoming      = *PI++;
    } else {
      Incoming      = *PI++;
      BackEdgeBlock = *PI++;
    }
    assert(PI == pred_end(Header) && "Loop headers should have 2 preds!");

    // Add incoming values for the PHI node...
    PN->addIncoming(Constant::getNullValue(IVType), Incoming);
    PN->addIncoming(Add, BackEdgeBlock);

    // Analyze the new induction variable...
    IndVars.push_back(InductionVariable(PN, Loops));
    assert(IndVars.back().InductionType == InductionVariable::Canonical &&
           "Just inserted canonical indvar that is not canonical!");
    Canonical = &IndVars.back();
    ++NumInserted;
    Changed = true;
  } else {
    // If we have a canonical induction variable, make sure that it is the first
    // one in the basic block.
    if (&Header->front() != Canonical->Phi)
      Header->getInstList().splice(Header->begin(), Header->getInstList(),
                                   Canonical->Phi);
  }

  DEBUG(std::cerr << "Induction variables:\n");

  // Get the current loop iteration count, which is always the value of the
  // canonical phi node...
  //
  PHINode *IterCount = Canonical->Phi;

  // Loop through and replace all of the auxiliary induction variables with
  // references to the canonical induction variable...
  //
  for (unsigned i = 0; i != IndVars.size(); ++i) {
    InductionVariable *IV = &IndVars[i];

    DEBUG(IV->print(std::cerr));

    while (isa<PHINode>(AfterPHIIt)) ++AfterPHIIt;

    // Don't modify the canonical indvar or unrecognized indvars...
    if (IV != Canonical && IV->InductionType != InductionVariable::Unknown) {
      const Type *IVTy = IV->Phi->getType();
      if (isa<PointerType>(IVTy))    // If indexing into a pointer, make the
        IVTy = TD->getIntPtrType();  // index the appropriate type.

      Instruction *Val = IterCount;
      if (!isa<ConstantInt>(IV->Step) ||   // If the step != 1
          !cast<ConstantInt>(IV->Step)->equalsInt(1)) {

        // If the types are not compatible, insert a cast now...
        if (Val->getType() != IVTy)
          Val = new CastInst(Val, IVTy, Val->getName(), AfterPHIIt);
        if (IV->Step->getType() != IVTy)
          IV->Step = new CastInst(IV->Step, IVTy, IV->Step->getName(),
                                  AfterPHIIt);

        Val = BinaryOperator::create(Instruction::Mul, Val, IV->Step,
                                     IV->Phi->getName()+"-scale", AfterPHIIt);
      }

      // If this is a pointer indvar...
      if (isa<PointerType>(IV->Phi->getType())) {
        std::vector<Value*> Idx;
        // FIXME: this should not be needed when we fix PR82!
        if (Val->getType() != Type::LongTy)
          Val = new CastInst(Val, Type::LongTy, Val->getName(), AfterPHIIt);
        Idx.push_back(Val);
        Val = new GetElementPtrInst(IV->Start, Idx,
                                    IV->Phi->getName()+"-offset",
                                    AfterPHIIt);

      } else if (!isa<Constant>(IV->Start) ||   // If Start != 0...
                 !cast<Constant>(IV->Start)->isNullValue()) {
        // If the types are not compatible, insert a cast now...
        if (Val->getType() != IVTy)
          Val = new CastInst(Val, IVTy, Val->getName(), AfterPHIIt);
        if (IV->Start->getType() != IVTy)
          IV->Start = new CastInst(IV->Start, IVTy, IV->Start->getName(),
                                   AfterPHIIt);

        // Insert the instruction after the phi nodes...
        Val = BinaryOperator::create(Instruction::Add, Val, IV->Start,
                                     IV->Phi->getName()+"-offset", AfterPHIIt);
      }

      // If the PHI node has a different type than val is, insert a cast now...
      if (Val->getType() != IV->Phi->getType())
        Val = new CastInst(Val, IV->Phi->getType(), Val->getName(), AfterPHIIt);

      // Replace all uses of the old PHI node with the new computed value...
      IV->Phi->replaceAllUsesWith(Val);

      // Move the PHI name to it's new equivalent value...
      std::string OldName = IV->Phi->getName();
      IV->Phi->setName("");
      Val->setName(OldName);

      // Get the incoming values used by the PHI node
      std::vector<Value*> PHIOps;
      PHIOps.reserve(IV->Phi->getNumIncomingValues());
      for (unsigned i = 0, e = IV->Phi->getNumIncomingValues(); i != e; ++i)
        PHIOps.push_back(IV->Phi->getIncomingValue(i));

      // Delete the old, now unused, phi node...
      Header->getInstList().erase(IV->Phi);

      // If the PHI is the last user of any instructions for computing PHI nodes
      // that are irrelevant now, delete those instructions.
      while (!PHIOps.empty()) {
        Instruction *MaybeDead = dyn_cast<Instruction>(PHIOps.back());
        PHIOps.pop_back();

        if (MaybeDead && isInstructionTriviallyDead(MaybeDead)) {
          PHIOps.insert(PHIOps.end(), MaybeDead->op_begin(),
                        MaybeDead->op_end());
          MaybeDead->getParent()->getInstList().erase(MaybeDead);

          // Erase any duplicates entries in the PHIOps list.
          std::vector<Value*>::iterator It =
            std::find(PHIOps.begin(), PHIOps.end(), MaybeDead);
          while (It != PHIOps.end()) {
            PHIOps.erase(It);
            It = std::find(PHIOps.begin(), PHIOps.end(), MaybeDead);
          }

          // Erasing the instruction could invalidate the AfterPHI iterator!
          AfterPHIIt = Header->begin();
        }
      }

      Changed = true;
      ++NumRemoved;
    }
  }

  return Changed;
}

<commit_msg>Don't mind me, I'm just refactoring away.  This patch makes room for LFTR, but contains no functionality changes.<commit_after>//===- IndVarSimplify.cpp - Induction Variable Elimination ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Guarantees that all loops with identifiable, linear, induction variables will
// be transformed to have a single, canonical, induction variable.  After this
// pass runs, it guarantees the the first PHI node of the header block in the
// loop is the canonical induction variable if there is one.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar.h"
#include "llvm/Constants.h"
#include "llvm/Type.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/InductionVariable.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Support/CFG.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/Utils/Local.h"
#include "Support/Debug.h"
#include "Support/Statistic.h"
using namespace llvm;

namespace {
  Statistic<> NumRemoved ("indvars", "Number of aux indvars removed");
  Statistic<> NumInserted("indvars", "Number of canonical indvars added");

  class IndVarSimplify : public FunctionPass {
    LoopInfo *Loops;
    TargetData *TD;
  public:
    virtual bool runOnFunction(Function &) {
      Loops = &getAnalysis<LoopInfo>();
      TD = &getAnalysis<TargetData>();

      // Induction Variables live in the header nodes of loops
      bool Changed = false;
      for (unsigned i = 0, e = Loops->getTopLevelLoops().size(); i != e; ++i)
        Changed |= runOnLoop(Loops->getTopLevelLoops()[i]);
      return Changed;
    }

    unsigned getTypeSize(const Type *Ty) {
      if (unsigned Size = Ty->getPrimitiveSize())
        return Size;
      return TD->getTypeSize(Ty);  // Must be a pointer
    }

    Value *ComputeAuxIndVarValue(InductionVariable &IV, Value *CIV);
    void ReplaceIndVar(InductionVariable &IV, Value *Counter);

    bool runOnLoop(Loop *L);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<TargetData>();   // Need pointer size
      AU.addRequired<LoopInfo>();
      AU.addRequiredID(LoopSimplifyID);
      AU.addPreservedID(LoopSimplifyID);
      AU.setPreservesCFG();
    }
  };
  RegisterOpt<IndVarSimplify> X("indvars", "Canonicalize Induction Variables");
}

Pass *llvm::createIndVarSimplifyPass() {
  return new IndVarSimplify();
}

bool IndVarSimplify::runOnLoop(Loop *Loop) {
  // Transform all subloops before this loop...
  bool Changed = false;
  for (unsigned i = 0, e = Loop->getSubLoops().size(); i != e; ++i)
    Changed |= runOnLoop(Loop->getSubLoops()[i]);

  // Get the header node for this loop.  All of the phi nodes that could be
  // induction variables must live in this basic block.
  //
  BasicBlock *Header = Loop->getHeader();

  // Loop over all of the PHI nodes in the basic block, calculating the
  // induction variables that they represent... stuffing the induction variable
  // info into a vector...
  //
  std::vector<InductionVariable> IndVars;    // Induction variables for block
  BasicBlock::iterator AfterPHIIt = Header->begin();
  for (; PHINode *PN = dyn_cast<PHINode>(AfterPHIIt); ++AfterPHIIt)
    IndVars.push_back(InductionVariable(PN, Loops));
  // AfterPHIIt now points to first non-phi instruction...

  // If there are no phi nodes in this basic block, there can't be indvars...
  if (IndVars.empty()) return Changed;

  // Loop over the induction variables, looking for a canonical induction
  // variable, and checking to make sure they are not all unknown induction
  // variables.  Keep track of the largest integer size of the induction
  // variable.
  //
  InductionVariable *Canonical = 0;
  unsigned MaxSize = 0;

  for (unsigned i = 0; i != IndVars.size(); ++i) {
    InductionVariable &IV = IndVars[i];

    if (IV.InductionType != InductionVariable::Unknown) {
      unsigned IVSize = getTypeSize(IV.Phi->getType());

      if (IV.InductionType == InductionVariable::Canonical &&
          !isa<PointerType>(IV.Phi->getType()) && IVSize >= MaxSize)
        Canonical = &IV;

      if (IVSize > MaxSize) MaxSize = IVSize;

      // If this variable is larger than the currently identified canonical
      // indvar, the canonical indvar is not usable.
      if (Canonical && IVSize > getTypeSize(Canonical->Phi->getType()))
        Canonical = 0;
    }
  }

  // No induction variables, bail early... don't add a canonical indvar
  if (MaxSize == 0) return Changed;

  // Okay, we want to convert other induction variables to use a canonical
  // indvar.  If we don't have one, add one now...
  if (!Canonical) {
    // Create the PHI node for the new induction variable, and insert the phi
    // node at the start of the PHI nodes...
    const Type *IVType;
    switch (MaxSize) {
    default: assert(0 && "Unknown integer type size!");
    case 1: IVType = Type::UByteTy; break;
    case 2: IVType = Type::UShortTy; break;
    case 4: IVType = Type::UIntTy; break;
    case 8: IVType = Type::ULongTy; break;
    }

    PHINode *PN = new PHINode(IVType, "cann-indvar", Header->begin());

    // Create the increment instruction to add one to the counter...
    Instruction *Add = BinaryOperator::create(Instruction::Add, PN,
                                              ConstantUInt::get(IVType, 1),
                                              "next-indvar", AfterPHIIt);

    // Figure out which block is incoming and which is the backedge for the loop
    BasicBlock *Incoming, *BackEdgeBlock;
    pred_iterator PI = pred_begin(Header);
    assert(PI != pred_end(Header) && "Loop headers should have 2 preds!");
    if (Loop->contains(*PI)) {  // First pred is back edge...
      BackEdgeBlock = *PI++;
      Incoming      = *PI++;
    } else {
      Incoming      = *PI++;
      BackEdgeBlock = *PI++;
    }
    assert(PI == pred_end(Header) && "Loop headers should have 2 preds!");

    // Add incoming values for the PHI node...
    PN->addIncoming(Constant::getNullValue(IVType), Incoming);
    PN->addIncoming(Add, BackEdgeBlock);

    // Analyze the new induction variable...
    IndVars.push_back(InductionVariable(PN, Loops));
    assert(IndVars.back().InductionType == InductionVariable::Canonical &&
           "Just inserted canonical indvar that is not canonical!");
    Canonical = &IndVars.back();
    ++NumInserted;
    Changed = true;
  } else {
    // If we have a canonical induction variable, make sure that it is the first
    // one in the basic block.
    if (&Header->front() != Canonical->Phi)
      Header->getInstList().splice(Header->begin(), Header->getInstList(),
                                   Canonical->Phi);
  }

  DEBUG(std::cerr << "Induction variables:\n");

  // Get the current loop iteration count, which is always the value of the
  // canonical phi node...
  //
  PHINode *IterCount = Canonical->Phi;

  // Loop through and replace all of the auxiliary induction variables with
  // references to the canonical induction variable...
  //
  for (unsigned i = 0; i != IndVars.size(); ++i) {
    InductionVariable *IV = &IndVars[i];

    DEBUG(IV->print(std::cerr));

    // Don't modify the canonical indvar or unrecognized indvars...
    if (IV != Canonical && IV->InductionType != InductionVariable::Unknown) {
      ReplaceIndVar(*IV, IterCount);
      Changed = true;
      ++NumRemoved;
    }
  }

  return Changed;
}

/// ComputeAuxIndVarValue - Given an auxillary induction variable, compute and
/// return a value which will always be equal to the induction variable PHI, but
/// is based off of the canonical induction variable CIV.
///
Value *IndVarSimplify::ComputeAuxIndVarValue(InductionVariable &IV, Value *CIV){
  Instruction *Phi = IV.Phi;
  const Type *IVTy = Phi->getType();
  if (isa<PointerType>(IVTy))    // If indexing into a pointer, make the
    IVTy = TD->getIntPtrType();  // index the appropriate type.

  BasicBlock::iterator AfterPHIIt = Phi;
  while (isa<PHINode>(AfterPHIIt)) ++AfterPHIIt;

  Value *Val = CIV;
  if (Val->getType() != IVTy)
    Val = new CastInst(Val, IVTy, Val->getName(), AfterPHIIt);

  if (!isa<ConstantInt>(IV.Step) ||   // If the step != 1
      !cast<ConstantInt>(IV.Step)->equalsInt(1)) {

    // If the types are not compatible, insert a cast now...
    if (IV.Step->getType() != IVTy)
      IV.Step = new CastInst(IV.Step, IVTy, IV.Step->getName(), AfterPHIIt);

    Val = BinaryOperator::create(Instruction::Mul, Val, IV.Step,
                                 Phi->getName()+"-scale", AfterPHIIt);
  }

  // If this is a pointer indvar...
  if (isa<PointerType>(Phi->getType())) {
    std::vector<Value*> Idx;
    // FIXME: this should not be needed when we fix PR82!
    if (Val->getType() != Type::LongTy)
      Val = new CastInst(Val, Type::LongTy, Val->getName(), AfterPHIIt);
    Idx.push_back(Val);
    Val = new GetElementPtrInst(IV.Start, Idx,
                                Phi->getName()+"-offset",
                                AfterPHIIt);

  } else if (!isa<Constant>(IV.Start) ||   // If Start != 0...
             !cast<Constant>(IV.Start)->isNullValue()) {
    // If the types are not compatible, insert a cast now...
    if (IV.Start->getType() != IVTy)
      IV.Start = new CastInst(IV.Start, IVTy, IV.Start->getName(),
                               AfterPHIIt);

    // Insert the instruction after the phi nodes...
    Val = BinaryOperator::create(Instruction::Add, Val, IV.Start,
                                 Phi->getName()+"-offset", AfterPHIIt);
  }

  // If the PHI node has a different type than val is, insert a cast now...
  if (Val->getType() != Phi->getType())
    Val = new CastInst(Val, Phi->getType(), Val->getName(), AfterPHIIt);

  // Move the PHI name to it's new equivalent value...
  std::string OldName = Phi->getName();
  Phi->setName("");
  Val->setName(OldName);

  return Val;
}

// ReplaceIndVar - Replace all uses of the specified induction variable with
// expressions computed from the specified loop iteration counter variable.
// Return true if instructions were deleted.
void IndVarSimplify::ReplaceIndVar(InductionVariable &IV, Value *CIV) {
  Value *IndVarVal = 0;
  PHINode *Phi = IV.Phi;

  assert(Phi->getNumOperands() == 4 &&
         "Only expect induction variables in canonical loops!");

  // Remember the incoming values used by the PHI node
  std::vector<Value*> PHIOps;
  PHIOps.reserve(2);
  PHIOps.push_back(Phi->getIncomingValue(0));
  PHIOps.push_back(Phi->getIncomingValue(1));

  // Delete all of the operands of the PHI node... FIXME, this should be more
  // intelligent.
  Phi->dropAllReferences();

  // Now that we are rid of unneeded uses of the PHI node, replace any remaining
  // ones with the appropriate code using the canonical induction variable.
  while (!Phi->use_empty()) {
    Instruction *U = cast<Instruction>(Phi->use_back());

    // TODO: Perform LFTR here if possible
    if (0) {

    } else {
      // Replace all uses of the old PHI node with the new computed value...
      if (IndVarVal == 0)
        IndVarVal = ComputeAuxIndVarValue(IV, CIV);
      U->replaceUsesOfWith(Phi, IndVarVal);
    }
  }

  // If the PHI is the last user of any instructions for computing PHI nodes
  // that are irrelevant now, delete those instructions.
  while (!PHIOps.empty()) {
    Instruction *MaybeDead = dyn_cast<Instruction>(PHIOps.back());
    PHIOps.pop_back();

    if (MaybeDead && isInstructionTriviallyDead(MaybeDead) &&
        (!isa<PHINode>(MaybeDead) ||
         MaybeDead->getParent() != Phi->getParent())) {
      PHIOps.insert(PHIOps.end(), MaybeDead->op_begin(),
                    MaybeDead->op_end());
      MaybeDead->getParent()->getInstList().erase(MaybeDead);

      // Erase any duplicates entries in the PHIOps list.
      std::vector<Value*>::iterator It =
        std::find(PHIOps.begin(), PHIOps.end(), MaybeDead);
      while (It != PHIOps.end()) {
        PHIOps.erase(It);
        It = std::find(PHIOps.begin(), PHIOps.end(), MaybeDead);
      }
    }
  }

  // Delete the old, now unused, phi node...
  Phi->getParent()->getInstList().erase(Phi);
}

<|endoftext|>


<commit_before>
#include <iostream>
#include <fstream>
#include <assert.h>

#include "mordorBinaryReader.hpp"
#include "mdataTools.hpp"
#include "readMData2.hpp"

using namespace std;

const int RECORD_SIZE = 75;

struct header{
  char* version;
  WORD numSpells;
};

struct header readHeader(ifstream *mdata){
  header ret;
  ret.version = readVBString(mdata);
  seekTo(mdata,RECORD_SIZE);
  ret.numSpells = readWord(mdata);
  seekTo(mdata,RECORD_SIZE);
  return ret;
}

struct Spell readSpell(ifstream *mdata){
  struct Spell thisSpell;
  thisSpell.name = readVBString(mdata);
  thisSpell.id = readWord(mdata);
  thisSpell.spellClass = readWord(mdata);
  thisSpell.level = readWord(mdata);
  thisSpell.u4 = readWord(mdata);
  assert(checkByteAlignment(mdata));
  thisSpell.killEffect = readWord(mdata);
  thisSpell.affectMonster = readWord(mdata);
  thisSpell.affectGroup = readWord(mdata);
  thisSpell.damage1 = readWord(mdata);
  thisSpell.damage2 = readWord(mdata);
  thisSpell.specialEffect = readWord(mdata);
  thisSpell.required = readWord(mdata);
  thisSpell.resistedBy = readWord(mdata);
  return thisSpell;
}

void printSpell(struct Spell *s){
  cout << s->name << endl;
  cout << "ID:\t\t\t" << s->id << endl;
  cout << "Class:\t\t\t" << s->spellClass << endl;
  cout << "Level:\t\t\t" << s->level << endl;
  cout << "U4:\t\t\t" << s->u4 << endl;
  cout << "KillEffect:\t\t" << s->killEffect << endl;
  cout << "Affect Monster:\t\t" << s->affectMonster << endl;
  cout << "Affect Group:\t\t" << s->affectGroup << endl;
  cout << "damage1:\t\t" << s->damage1 << endl;
  cout << "damage2:\t\t" << s->damage2 << endl;
  cout << "SpecialEffect:\t\t" << s->specialEffect << endl;
  cout << "Required:\t\t" << s->required << endl;
  cout << "Resisted By:\t\t" << s->resistedBy << endl;
}

int main(int argc, char** argv){
  char* datAbsolutePath;

  if(argc != 2){
    cerr << "Expected exactly one argument -- the absolute path to the MDAT12.MDR" << endl;
    return 1;
  }else{
    datAbsolutePath = argv[1];
  }

  if (not possiblyValidFile(datAbsolutePath, MDATA2)){
    cerr << datAbsolutePath << " doesn't appear to be a valid MDATA2.MDR" << endl;
    return 1;
  }

  ifstream mdata_input(datAbsolutePath, ios::binary | ios::in);

  // read file version, vb string
  header info = readHeader(&mdata_input);

  cout << "Version " << info.version << endl;

  // read spell list
  for(int i = 0; i < info.numSpells; i++){
    cout << "Reading spell " << dec << i << endl;
    struct Spell first = readSpell(&mdata_input);
    printSpell(&first);
    cout << endl;
    seekTo(&mdata_input,RECORD_SIZE);
  }

  /*
  mdata_input.seekg(0x00001f80);
  for(int i = 0; i < numSpells2; i++){
    cout << "Reading spell " << i << endl;
    spell first = readSpell(&mdata_input);
    printSpell(&first);
    cout << endl;
    seekTo(&mdata_input,RECORD_SIZE);
  }
  */
  return 0;
}
<commit_msg>cleaning up printing function<commit_after>
#include <iostream>
#include <fstream>
#include <assert.h>

#include "mordorBinaryReader.hpp"
#include "mdataTools.hpp"
#include "readMData2.hpp"

using namespace std;

const int RECORD_SIZE = 75;

struct header{
  char* version;
  WORD numSpells;
};

struct header readHeader(ifstream *mdata){
  header ret;
  ret.version = readVBString(mdata);
  seekTo(mdata,RECORD_SIZE);
  ret.numSpells = readWord(mdata);
  seekTo(mdata,RECORD_SIZE);
  return ret;
}

void printSpell(struct Spell *s){
  cout << s->name << endl
       << "ID:             " << s->id << endl
       << "Class:          " << s->spellClass << endl
       << "Level:          " << s->level << endl
       << "U4:             " << s->u4 << endl
       << "KillEffect:     " << s->killEffect << endl
       << "Affect Monster: " << s->affectMonster << endl
       << "Affect Group:   " << s->affectGroup << endl
       << "damage1:        " << s->damage1 << endl
       << "damage2:        " << s->damage2 << endl
       << "SpecialEffect:  " << s->specialEffect << endl
       << "Required:       " << s->required << endl
       << "Resisted By:    " << s->resistedBy << endl;
}

struct Spell readSpell(ifstream *mdata){
  struct Spell thisSpell;
  thisSpell.name = readVBString(mdata);
  thisSpell.id = readWord(mdata);
  thisSpell.spellClass = readWord(mdata);
  thisSpell.level = readWord(mdata);
  thisSpell.u4 = readWord(mdata);
  assert(checkByteAlignment(mdata));
  thisSpell.killEffect = readWord(mdata);
  thisSpell.affectMonster = readWord(mdata);
  thisSpell.affectGroup = readWord(mdata);
  thisSpell.damage1 = readWord(mdata);
  thisSpell.damage2 = readWord(mdata);
  thisSpell.specialEffect = readWord(mdata);
  thisSpell.required = readWord(mdata);
  thisSpell.resistedBy = readWord(mdata);

  printSpell(&thisSpell);
  seekTo(mdata,RECORD_SIZE);
  return thisSpell;
}

int main(int argc, char** argv){
  char* datAbsolutePath;

  if(argc != 2){
    cerr << "Expected exactly one argument -- the absolute path to the MDAT12.MDR"
         << endl;
    return 1;
  }else{
    datAbsolutePath = argv[1];
  }

  if (not possiblyValidFile(datAbsolutePath, MDATA2)){
    cerr << datAbsolutePath << " doesn't appear to be a valid MDATA2.MDR" << endl;
    return 1;
  }

  ifstream mdata_input(datAbsolutePath, ios::binary | ios::in);

  // read file version, vb string
  header info = readHeader(&mdata_input);

  cout << "Version " << info.version << endl;

  // read spell list
  for(int i = 0; i < info.numSpells; i++){
    cout << "Reading spell " << dec << i << endl;
    struct Spell first = readSpell(&mdata_input);
    cout << endl;
  }

  /*
  mdata_input.seekg(0x00001f80);
  for(int i = 0; i < numSpells2; i++){
    cout << "Reading spell " << i << endl;
    spell first = readSpell(&mdata_input);
    printSpell(&first);
    cout << endl;
    seekTo(&mdata_input,RECORD_SIZE);
  }
  */
  return 0;
}
<|endoftext|>


<commit_before>// request symbols
#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/CValuePrinter.h"
#include "cling/Interpreter/DynamicExprInfo.h"
#include "cling/Interpreter/InterpreterCallbacks.h"
#include "cling/Interpreter/LookupHelper.h"
#include "cling/Interpreter/ValuePrinter.h"
#include "cling/Interpreter/ValuePrinterInfo.h"
#include "cling/UserInterface/UserInterface.h"

#include "clang/AST/Type.h"

#include "llvm/Support/raw_ostream.h"

namespace cling {
void libcling__symbol_requester(const clang::FunctionDecl& Decl,
                                const cling::Interpreter& Interp,
                                clang::Parser* P) {
   const char* const argv[] = {"libcling__symbol_requester", 0};
   cling::Interpreter I(1, argv);
   cling::UserInterface U(I);
   cling::ValuePrinterInfo VPI(0, 0); // asserts, but we don't call.
   printValuePublicDefault(llvm::outs(), 0, VPI);
   cling_PrintValue(0, 0, 0);
   flushOStream(llvm::outs());
   LookupHelper h(P);
   h.findType("");
   h.findScope("");
   h.findFunctionProto(0, "", "");
   h.findFunctionArgs(0, "", "");
   cling::runtime::internal::DynamicExprInfo DEI(0,0,false);
   DEI.getExpr();
   cling::InterpreterCallbacks cb(0);
}
}
<commit_msg>My bad that shouldn't ended up in the trunk at all<commit_after><|endoftext|>


<commit_before>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#include <vector>
#include <numeric>

#include "gtest/gtest.h"

#include "xsimd/xsimd.hpp"

namespace xsimd
{
    struct interface_tester
    {
        std::vector<float, aligned_allocator<float, 32>> fvec;
        std::vector<int32_t, aligned_allocator<int32_t, 32>> ivec;
        std::vector<float, aligned_allocator<float, 32>> fres;
        std::vector<int32_t, aligned_allocator<int32_t, 32>> ires;

        interface_tester();
    };

    interface_tester::interface_tester()
        : fvec(8), ivec(8), fres(8), ires(8)
    {
        std::iota(fvec.begin(), fvec.end(), 1.f);
        std::iota(ivec.begin(), ivec.end(), 1);
    }

    TEST(xsimd, set_simd)
    {
        interface_tester t;
        simd_type<float> r1 = set_simd(t.fvec[0]);
        EXPECT_EQ(r1[0], t.fvec[0]);

        simd_type<float> r2 = set_simd<int32_t, float>(t.ivec[0]);
        EXPECT_EQ(r2[0], t.fvec[0]);
    }

    TEST(xsimd, load_store_aligned)
    {
        interface_tester t;
        simd_type<float> r1 = load_aligned(&t.fvec[0]);
        store_aligned(&t.fres[0], r1);
        EXPECT_EQ(t.fvec, t.fres);

        simd_type<float> r2 = load_aligned<int32_t, float>(&t.ivec[0]);
        store_aligned(&t.fres[0], r2);
        EXPECT_EQ(t.fvec, t.fres);

        simd_type<float> r3 = load_aligned(&t.fvec[0]);
        store_aligned<int32_t, float>(&t.ires[0], r3);
        EXPECT_EQ(t.ivec, t.ires);
    }

    TEST(xsimd, load_store_unaligned)
    {
        interface_tester t;
        simd_type<float> r1 = load_unaligned(&t.fvec[0]);
        store_unaligned(&t.fres[0], r1);
        EXPECT_EQ(t.fvec, t.fres);

        simd_type<float> r2 = load_unaligned<int32_t, float>(&t.ivec[0]);
        store_unaligned(&t.fres[0], r2);
        EXPECT_EQ(t.fvec, t.fres);

        simd_type<float> r3 = load_unaligned(&t.fvec[0]);
        store_unaligned<int32_t, float>(&t.ires[0], r3);
        EXPECT_EQ(t.ivec, t.ires);
    }

    TEST(xsimd, load_store_simd_aligned)
    {
        interface_tester t;
        simd_type<float> r1 = load_simd(&t.fvec[0], aligned_mode());
        store_simd(&t.fres[0], r1, aligned_mode());
        EXPECT_EQ(t.fvec, t.fres);

        simd_type<float> r2 = load_simd<int32_t, float>(&t.ivec[0], aligned_mode());
        store_simd(&t.fres[0], r2, aligned_mode());
        EXPECT_EQ(t.fvec, t.fres);

        simd_type<float> r3 = load_simd(&t.fvec[0], aligned_mode());
        store_simd<int32_t, float>(&t.ires[0], r3, aligned_mode());
        EXPECT_EQ(t.ivec, t.ires);
    }

    TEST(xsimd, load_store_simd_unaligned)
    {
        interface_tester t;
        simd_type<float> r1 = load_simd(&t.fvec[0], unaligned_mode());
        store_simd(&t.fres[0], r1, unaligned_mode());
        EXPECT_EQ(t.fvec, t.fres);

        simd_type<float> r2 = load_simd<int32_t, float>(&t.ivec[0], unaligned_mode());
        store_simd(&t.fres[0], r2, unaligned_mode());
        EXPECT_EQ(t.fvec, t.fres);

        simd_type<float> r3 = load_simd(&t.fvec[0], unaligned_mode());
        store_simd<int32_t, float>(&t.ires[0], r3, unaligned_mode());
        EXPECT_EQ(t.ivec, t.ires);
    }
}
<commit_msg>test of interface fixed<commit_after>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#include <cstddef>
#include <vector>
#include <numeric>

#include "gtest/gtest.h"

#include "xsimd/xsimd.hpp"

namespace xsimd
{
    struct interface_tester
    {
        std::vector<float, aligned_allocator<float, 32>> fvec;
        std::vector<int32_t, aligned_allocator<int32_t, 32>> ivec;
        std::vector<float, aligned_allocator<float, 32>> fres;
        std::vector<int32_t, aligned_allocator<int32_t, 32>> ires;

        interface_tester();

        static const std::size_t SIZE = simd_traits<float>::size;
    };

    interface_tester::interface_tester()
        : fvec(SIZE), ivec(SIZE), fres(SIZE), ires(SIZE)
    {
        std::iota(fvec.begin(), fvec.end(), 1.f);
        std::iota(ivec.begin(), ivec.end(), 1);
    }

    TEST(xsimd, set_simd)
    {
        interface_tester t;
        simd_type<float> r1 = set_simd(t.fvec[0]);
        EXPECT_EQ(r1[0], t.fvec[0]);

        simd_type<float> r2 = set_simd<int32_t, float>(t.ivec[0]);
        EXPECT_EQ(r2[0], t.fvec[0]);
    }

    TEST(xsimd, load_store_aligned)
    {
        interface_tester t;
        simd_type<float> r1 = load_aligned(&t.fvec[0]);
        store_aligned(&t.fres[0], r1);
        EXPECT_EQ(t.fvec, t.fres);

        simd_type<float> r2 = load_aligned<int32_t, float>(&t.ivec[0]);
        store_aligned(&t.fres[0], r2);
        EXPECT_EQ(t.fvec, t.fres);

        simd_type<float> r3 = load_aligned(&t.fvec[0]);
        store_aligned<int32_t, float>(&t.ires[0], r3);
        EXPECT_EQ(t.ivec, t.ires);
    }

    TEST(xsimd, load_store_unaligned)
    {
        interface_tester t;
        simd_type<float> r1 = load_unaligned(&t.fvec[0]);
        store_unaligned(&t.fres[0], r1);
        EXPECT_EQ(t.fvec, t.fres);

        simd_type<float> r2 = load_unaligned<int32_t, float>(&t.ivec[0]);
        store_unaligned(&t.fres[0], r2);
        EXPECT_EQ(t.fvec, t.fres);

        simd_type<float> r3 = load_unaligned(&t.fvec[0]);
        store_unaligned<int32_t, float>(&t.ires[0], r3);
        EXPECT_EQ(t.ivec, t.ires);
    }

    TEST(xsimd, load_store_simd_aligned)
    {
        interface_tester t;
        simd_type<float> r1 = load_simd(&t.fvec[0], aligned_mode());
        store_simd(&t.fres[0], r1, aligned_mode());
        EXPECT_EQ(t.fvec, t.fres);

        simd_type<float> r2 = load_simd<int32_t, float>(&t.ivec[0], aligned_mode());
        store_simd(&t.fres[0], r2, aligned_mode());
        EXPECT_EQ(t.fvec, t.fres);

        simd_type<float> r3 = load_simd(&t.fvec[0], aligned_mode());
        store_simd<int32_t, float>(&t.ires[0], r3, aligned_mode());
        EXPECT_EQ(t.ivec, t.ires);
    }

    TEST(xsimd, load_store_simd_unaligned)
    {
        interface_tester t;
        simd_type<float> r1 = load_simd(&t.fvec[0], unaligned_mode());
        store_simd(&t.fres[0], r1, unaligned_mode());
        EXPECT_EQ(t.fvec, t.fres);

        simd_type<float> r2 = load_simd<int32_t, float>(&t.ivec[0], unaligned_mode());
        store_simd(&t.fres[0], r2, unaligned_mode());
        EXPECT_EQ(t.fvec, t.fres);

        simd_type<float> r3 = load_simd(&t.fvec[0], unaligned_mode());
        store_simd<int32_t, float>(&t.ires[0], r3, unaligned_mode());
        EXPECT_EQ(t.ivec, t.ires);
    }
}
<|endoftext|>


<commit_before>/**
 * A class which represents the properties and actions of a POSIX TCP socket.
 *
 * @date                    July 6, 2014
 * @author                    Joeri HERMANS
 * @version                    0.1
 *
 * Copyright 2013 Joeri HERMANS
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// BEGIN Includes. ///////////////////////////////////////////////////

// System dependencies.
#include <cassert>
#include <cstring>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netinet/in.h>
#include <iostream>
#include <poll.h>
#include <netdb.h>
#include <errno.h>

// Application dependencies.
#include <ias/io/reader/network/posix/posix_tcp_socket_reader.h>
#include <ias/io/writer/network/posix/posix_tcp_socket_writer.h>
#include <ias/network/posix/posix_tcp_socket.h>
#include <ias/network/util.h>

// END Includes. /////////////////////////////////////////////////////

inline void PosixTcpSocket::initialize( void ) {
    setFileDescriptor(-1);
    mReader = nullptr;
    mWriter = nullptr;
}

void PosixTcpSocket::setFileDescriptor( const int fd ) {
    // Checking the precondition.
    assert( fd >= -1 );

    mFileDescriptor = fd;
}

void PosixTcpSocket::setKeepAlive( void ) {
    static const int optval = 1;

    setsockopt(mFileDescriptor,SOL_SOCKET,SO_KEEPALIVE,&optval,sizeof optval);
}

bool PosixTcpSocket::initializeConnection( const std::string & address,
                                           const std::size_t port ) {
    bool connected;
    int fd;

    fd = connect(address,port);
    if( fd >= 0 ) {
        mFileDescriptor = fd;
        setKeepAlive();
        connected = true;
        delete mReader; mReader = nullptr;
        delete mWriter; mWriter = nullptr;
        mReader = new PosixTcpSocketReader(this);
        mWriter = new PosixTcpSocketWriter(this);
    } else {
        connected = false;
    }

    return ( connected );
}

void PosixTcpSocket::pollSocket( void ) const {
    struct pollfd pfd;

    if( mFileDescriptor >= 0 ) {
        pfd.fd = mFileDescriptor;
        #if defined(__linux__)
        pfd.events = POLLNVAL | POLLHUP | POLLRDHUP;
        #else
        pfd.events = POLLNVAL | POLLHUP;
        #endif
        pfd.revents = 0;
        if( poll(&pfd,1,0) >= 1 ) {
            close(mFileDescriptor);
            mFileDescriptor = -1;
        }
    }
}

PosixTcpSocket::PosixTcpSocket( void ) {
    initialize();
}

PosixTcpSocket::PosixTcpSocket( const int fd ) {
    setFileDescriptor(fd);
    // Allocate reader and writer.
    mReader = new PosixTcpSocketReader(this);
    mWriter = new PosixTcpSocketWriter(this);
}

PosixTcpSocket::~PosixTcpSocket( void ) {
    closeConnection();
    delete mReader; mReader = nullptr;
    delete mWriter; mWriter = nullptr;
}

void PosixTcpSocket::closeConnection( void ) {
    if( isConnected() )
        close(mFileDescriptor);
    setFileDescriptor(-1);
}

bool PosixTcpSocket::createConnection( const std::string & address,
                                       const std::size_t port ) {
    closeConnection();

    return ( initializeConnection(address,port) );
}

bool PosixTcpSocket::isConnected( void ) const {
    pollSocket();

    return ( mFileDescriptor >= 0 );
}

Reader * PosixTcpSocket::getReader( void ) const {
    return ( mReader );
}

Writer * PosixTcpSocket::getWriter( void ) const {
    return ( mWriter );
}

int PosixTcpSocket::getFileDescriptor( void ) const {
    return ( mFileDescriptor );
}
<commit_msg>Add KEEPALIVE.<commit_after>/**
 * A class which represents the properties and actions of a POSIX TCP socket.
 *
 * @date                    July 6, 2014
 * @author                    Joeri HERMANS
 * @version                    0.1
 *
 * Copyright 2013 Joeri HERMANS
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// BEGIN Includes. ///////////////////////////////////////////////////

// System dependencies.
#include <cassert>
#include <cstring>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netinet/in.h>
#include <iostream>
#include <poll.h>
#include <netdb.h>
#include <errno.h>

// Application dependencies.
#include <ias/io/reader/network/posix/posix_tcp_socket_reader.h>
#include <ias/io/writer/network/posix/posix_tcp_socket_writer.h>
#include <ias/network/posix/posix_tcp_socket.h>
#include <ias/network/util.h>

// END Includes. /////////////////////////////////////////////////////

inline void PosixTcpSocket::initialize( void ) {
    setFileDescriptor(-1);
    mReader = nullptr;
    mWriter = nullptr;
}

void PosixTcpSocket::setFileDescriptor( const int fd ) {
    // Checking the precondition.
    assert( fd >= -1 );

    mFileDescriptor = fd;
}

#include <iostream>

void PosixTcpSocket::setKeepAlive( void ) {
    static const int optval = 1;

    setsockopt(mFileDescriptor,SOL_SOCKET,SO_KEEPALIVE,&optval,sizeof optval);
}

bool PosixTcpSocket::initializeConnection( const std::string & address,
                                           const std::size_t port ) {
    bool connected;
    int fd;

    fd = connect(address,port);
    if( fd >= 0 ) {
        mFileDescriptor = fd;
        setKeepAlive();
        connected = true;
        delete mReader; mReader = nullptr;
        delete mWriter; mWriter = nullptr;
        mReader = new PosixTcpSocketReader(this);
        mWriter = new PosixTcpSocketWriter(this);
    } else {
        connected = false;
    }

    return ( connected );
}

void PosixTcpSocket::pollSocket( void ) const {
    struct pollfd pfd;

    if( mFileDescriptor >= 0 ) {
        pfd.fd = mFileDescriptor;
        #if defined(__linux__)
        pfd.events = POLLNVAL | POLLHUP | POLLRDHUP;
        #else
        pfd.events = POLLNVAL | POLLHUP;
        #endif
        pfd.revents = 0;
        if( poll(&pfd,1,0) >= 1 ) {
            close(mFileDescriptor);
            mFileDescriptor = -1;
        }
    }
}

PosixTcpSocket::PosixTcpSocket( void ) {
    initialize();
}

PosixTcpSocket::PosixTcpSocket( const int fd ) {
    setFileDescriptor(fd);
    // Allocate reader and writer.
    mReader = new PosixTcpSocketReader(this);
    mWriter = new PosixTcpSocketWriter(this);
}

PosixTcpSocket::~PosixTcpSocket( void ) {
    closeConnection();
    delete mReader; mReader = nullptr;
    delete mWriter; mWriter = nullptr;
}

void PosixTcpSocket::closeConnection( void ) {
    if( isConnected() )
        close(mFileDescriptor);
    setFileDescriptor(-1);
}

bool PosixTcpSocket::createConnection( const std::string & address,
                                       const std::size_t port ) {
    closeConnection();

    return ( initializeConnection(address,port) );
}

bool PosixTcpSocket::isConnected( void ) const {
    pollSocket();

    return ( mFileDescriptor >= 0 );
}

Reader * PosixTcpSocket::getReader( void ) const {
    return ( mReader );
}

Writer * PosixTcpSocket::getWriter( void ) const {
    return ( mWriter );
}

int PosixTcpSocket::getFileDescriptor( void ) const {
    return ( mFileDescriptor );
}
<|endoftext|>


<commit_before>
/* Portions copyright (c) 2006 Stanford University and Jack Middleton.
 * Contributors:
 *
 * 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 "Simmath.h"
#include "Optimizer.h"
#include "LBFGSOptimizer.h"
#include "LBFGSBOptimizer.h"
#include "InteriorPointOptimizer.h"

namespace SimTK {

   Optimizer::~Optimizer() {
         delete( (OptimizerRep *)rep );
      }

void Optimizer::librarySideOptimizerConstructor( OptimizerSystem& sys ) {

      if( sys.getNumConstraints() > 0)   {
         rep = (OptimizerRep *) new InteriorPointOptimizer( sys  );
      }else if( sys.getHasLimits() ) {
         rep = (OptimizerRep *) new LBFGSBOptimizer( sys  );
      } else {
         rep = (OptimizerRep *) new LBFGSOptimizer( sys  );
      }
      rep->setMyHandle(*this);
      updRep().sysp = &sys;
}

void Optimizer::useNumericalGradient( const bool flag ) {

      ((OptimizerRep *)rep)->useNumericalGradient(flag);
      return;
}
void Optimizer::useNumericalJacobian( const bool flag )  {

      ((OptimizerRep *)rep)->useNumericalJacobian(flag);
      return;
}

void Optimizer::setConvergenceTolerance( const Real tolerance ){

      ((OptimizerRep *)rep)->setConvergenceTolerance(tolerance);
      return;
}

void Optimizer::setDiagnosticsLevel( const int  level ){

      ((OptimizerRep *)rep)->setDiagnosticsLevel(level);
      return;
}

int Optimizer::setAdvancedOptions( const char *option, const Real *values ){

      return( ((OptimizerRep *)rep)->setAdvancedOptions( option, values) );
}

Real Optimizer::optimize(SimTK::Vector   &results) {
      return( ((OptimizerRep *)rep)->optimize(results) );
}

int objectiveFuncWrapper( int n, Real *x, int new_x,  Real *f, void* user_data) {
      Vector parameters( n, x, true);
      Real& frep = *f;
      const OptimizerRep& rep = *reinterpret_cast<const OptimizerRep*>(user_data);
      if( 0 == rep.objectiveFunc( rep.getOptimizerSystem(), parameters, new_x, frep )) {
          return(1);
      } else {
          return(0);
      }
}
int gradientFuncWrapper( int n, Real *x, int new_x, Real *gradient, void* user_data) {

      Real fy0;
      Real& sfy0 = fy0;
      Vector params( n, x, true);
      Vector grad_vec(n,gradient,true);
      const OptimizerRep& rep = *reinterpret_cast<const OptimizerRep*>(user_data);

      if( rep.getNumericalGradient() ) {
          rep.getOptimizerSystem().objectiveFunc( params, true, sfy0 );
          rep.gradDiff->calcGradient( params, sfy0, grad_vec);
          return(1);
      } else {
          if( 0 == rep.gradientFunc( rep.getOptimizerSystem(), params, new_x, grad_vec )) {
            return(1);
          } else {
            return(0);
          }
      }

}
int constraintFuncWrapper( int n, Real *x, int new_x, int m, Real *g,  void*user_data) {
      Vector parameters( n, x, true);
      Vector constraints(m, g, true);
      const OptimizerRep& rep = *reinterpret_cast<const OptimizerRep*>(user_data);
      if( 0 == rep.constraintFunc( rep.getOptimizerSystem(), parameters, new_x, constraints )) {
         return 1;
      } else {
         return 0;
      }
}
int constraintJacobianWrapper(int n, Real *x, int new_x, int m, Index nele_jac,
                int *iRow, int *jCol, Real *values, void *user_data)
{
  int i,j,index;
  if (values == NULL) {

    /* always assume  the jacobian is dense */
    index = 0;
    for(j=0;j<m;j++) {
      for(i=0;i<n;i++) {
          iRow[index] = j;
          jCol[index++] = i;
//printf("IROW=%d JCol=%d \n",iRow[index-1],jCol[index-1]);
       }
    }
  } else {
    /* jacobian of the constraints */

    Vector params(n,x,true);
    const OptimizerRep& rep = *reinterpret_cast<const OptimizerRep*>(user_data);

    Matrix jac(m,n);

    if( rep.getNumericalJacobian() ) {
        Vector sfy0(m);
        rep.getOptimizerSystem().constraintFunc( params, true, sfy0 );
        rep.jacDiff->calcJacobian( params, sfy0, jac);

    } else {

        rep.constraintJacobian( rep.getOptimizerSystem(), params, new_x, jac );

    }
    /* transpose the jacobian because Ipopt indexes in Row major format */
    Real *ptr = values;
    for(j=0;j<m;j++) {
        for(i=0;i<n;i++,ptr++) {
            *ptr = jac(j,i);
        }
    }
//   std::cout << std::setprecision(20);
//   std::cout << jac << std::endl << std::endl;

  }
  return( 1 );
}
// TODO finish hessianWrapper
int hessianWrapper(int n, Real *x, int new_x, Real obj_factor,
            int m, Number *lambda, int new_lambda,
            int nele_hess, int *iRow, int *jCol,
            Real *values, void *user_data) {

    Vector coeff(n,x,true);
    Vector hess(n*n,values,true);
    const OptimizerRep& rep = *reinterpret_cast<const OptimizerRep*>(user_data);
    return( rep.hessian( rep.getOptimizerSystem(), coeff, new_x, hess ));
}

void Optimizer::registerObjectiveFunc(Optimizer::ObjectiveFunc f) {
    updRep().objectiveFunc = f;
}
void Optimizer::registerGradientFunc(Optimizer::GradientFunc f) {
    updRep().gradientFunc = f;
}
void Optimizer::registerConstraintFunc(Optimizer::ConstraintFunc f) {
    updRep().constraintFunc = f;
}
void Optimizer::registerConstraintJacobian(Optimizer::ConstraintJacobian f) {
    updRep().constraintJacobian = f;
}
void Optimizer::registerHessian(Optimizer::Hessian f) {
    updRep().hessian = f;
}

} // namespace SimTK
<commit_msg>pass new_x as bool to user functions<commit_after>
/* Portions copyright (c) 2006 Stanford University and Jack Middleton.
 * Contributors:
 *
 * 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 "Simmath.h"
#include "Optimizer.h"
#include "LBFGSOptimizer.h"
#include "LBFGSBOptimizer.h"
#include "InteriorPointOptimizer.h"

namespace SimTK {

   Optimizer::~Optimizer() {
         delete( (OptimizerRep *)rep );
      }

void Optimizer::librarySideOptimizerConstructor( OptimizerSystem& sys ) {

      if( sys.getNumConstraints() > 0)   {
         rep = (OptimizerRep *) new InteriorPointOptimizer( sys  );
      }else if( sys.getHasLimits() ) {
         rep = (OptimizerRep *) new LBFGSBOptimizer( sys  );
      } else {
         rep = (OptimizerRep *) new LBFGSOptimizer( sys  );
      }
      rep->setMyHandle(*this);
      updRep().sysp = &sys;
}

void Optimizer::useNumericalGradient( const bool flag ) {

      ((OptimizerRep *)rep)->useNumericalGradient(flag);
      return;
}
void Optimizer::useNumericalJacobian( const bool flag )  {

      ((OptimizerRep *)rep)->useNumericalJacobian(flag);
      return;
}

void Optimizer::setConvergenceTolerance( const Real tolerance ){

      ((OptimizerRep *)rep)->setConvergenceTolerance(tolerance);
      return;
}

void Optimizer::setDiagnosticsLevel( const int  level ){

      ((OptimizerRep *)rep)->setDiagnosticsLevel(level);
      return;
}

int Optimizer::setAdvancedOptions( const char *option, const Real *values ){

      return( ((OptimizerRep *)rep)->setAdvancedOptions( option, values) );
}

Real Optimizer::optimize(SimTK::Vector   &results) {
      return( ((OptimizerRep *)rep)->optimize(results) );
}

int objectiveFuncWrapper( int n, Real *x, int new_x,  Real *f, void* user_data) {
      Vector parameters( n, x, true);
      Real& frep = *f;
      bool new_param;
      if( new_x == 1 )
          new_param = true;
      else
          new_param = false;
      const OptimizerRep& rep = *reinterpret_cast<const OptimizerRep*>(user_data);
      if( 0 == rep.objectiveFunc( rep.getOptimizerSystem(), parameters, new_param, frep )) {
          return(1);
      } else {
          return(0);
      }
}
int gradientFuncWrapper( int n, Real *x, int new_x, Real *gradient, void* user_data) {

      Real fy0;
      Real& sfy0 = fy0;
      Vector params( n, x, true);
      Vector grad_vec(n,gradient,true);
      const OptimizerRep& rep = *reinterpret_cast<const OptimizerRep*>(user_data);
      bool new_param;
      if( new_x == 1 )
          new_param = true;
      else
          new_param = false;

      if( rep.getNumericalGradient() ) {
          rep.getOptimizerSystem().objectiveFunc( params, true, sfy0 );
          rep.gradDiff->calcGradient( params, sfy0, grad_vec);
          return(1);
      } else {
          if( 0 == rep.gradientFunc( rep.getOptimizerSystem(), params, new_param, grad_vec )) {
            return(1);
          } else {
            return(0);
          }
      }

}
int constraintFuncWrapper( int n, Real *x, int new_x, int m, Real *g,  void*user_data) {
      Vector parameters( n, x, true);
      Vector constraints(m, g, true);
      const OptimizerRep& rep = *reinterpret_cast<const OptimizerRep*>(user_data);
      bool new_param;

      if( new_x == 1 )
          new_param = true;
      else
          new_param = false;
      if( 0 == rep.constraintFunc( rep.getOptimizerSystem(), parameters, new_param, constraints )) {
         return 1;
      } else {
         return 0;
      }
}
int constraintJacobianWrapper(int n, Real *x, int new_x, int m, Index nele_jac,
                int *iRow, int *jCol, Real *values, void *user_data)
{
  int i,j,index;
  bool new_param;
  if( new_x == 1 )
      new_param = true;
  else
      new_param = false;

  if (values == NULL) {

    /* always assume  the jacobian is dense */
    index = 0;
    for(j=0;j<m;j++) {
      for(i=0;i<n;i++) {
          iRow[index] = j;
          jCol[index++] = i;
//printf("IROW=%d JCol=%d \n",iRow[index-1],jCol[index-1]);
       }
    }
  } else {
    /* jacobian of the constraints */

    Vector params(n,x,true);
    const OptimizerRep& rep = *reinterpret_cast<const OptimizerRep*>(user_data);

    Matrix jac(m,n);

    if( rep.getNumericalJacobian() ) {
        Vector sfy0(m);
        rep.getOptimizerSystem().constraintFunc( params, true, sfy0 );
        rep.jacDiff->calcJacobian( params, sfy0, jac);

    } else {

        rep.constraintJacobian( rep.getOptimizerSystem(), params, new_param, jac );

    }
    /* transpose the jacobian because Ipopt indexes in Row major format */
    Real *ptr = values;
    for(j=0;j<m;j++) {
        for(i=0;i<n;i++,ptr++) {
            *ptr = jac(j,i);
        }
    }
//   std::cout << std::setprecision(20);
//   std::cout << jac << std::endl << std::endl;

  }
  return( 1 );
}
// TODO finish hessianWrapper
int hessianWrapper(int n, Real *x, int new_x, Real obj_factor,
            int m, Number *lambda, int new_lambda,
            int nele_hess, int *iRow, int *jCol,
            Real *values, void *user_data) {

    Vector coeff(n,x,true);
    Vector hess(n*n,values,true);
    const OptimizerRep& rep = *reinterpret_cast<const OptimizerRep*>(user_data);
    bool new_param;
    if( new_x == 1 )
       new_param = true;
    else
       new_param = false;

    return( rep.hessian( rep.getOptimizerSystem(), coeff, new_param, hess ));
}

void Optimizer::registerObjectiveFunc(Optimizer::ObjectiveFunc f) {
    updRep().objectiveFunc = f;
}
void Optimizer::registerGradientFunc(Optimizer::GradientFunc f) {
    updRep().gradientFunc = f;
}
void Optimizer::registerConstraintFunc(Optimizer::ConstraintFunc f) {
    updRep().constraintFunc = f;
}
void Optimizer::registerConstraintJacobian(Optimizer::ConstraintJacobian f) {
    updRep().constraintJacobian = f;
}
void Optimizer::registerHessian(Optimizer::Hessian f) {
    updRep().hessian = f;
}

} // namespace SimTK
<|endoftext|>


<commit_before>//Copyright 2011-2018 Tyler Gilbert; All Rights Reserved

#include <cstdio>
#include <errno.h>
#include "var/Token.hpp"
#include "sys/File.hpp"
#include "sgfx/Font.hpp"

using namespace sgfx;

FontInfo::FontInfo(u8 point_size, u8 style, const Font * font){
	m_point_size = point_size;
	m_style = style;
	m_font = font;
}

FontInfo::FontInfo(const var::ConstString & path){
	m_path = path;

	var::Tokenizer tokens(sys::File::name(path), "-.");

	if( tokens.count() != 4 ){
		m_point_size = 0;
		printf("Font name is not valid\n");
	} else {

		m_font = 0;
		m_name = tokens.at(0);
		m_point_size = tokens.at(2).to_integer();
		var::String style = tokens.at(1);
		style.to_lower();

		m_style = ANY;
		if( style == "t" ){ m_style = THIN; }
		if( style == "ti" ){ m_style = THIN_ITALIC; }
		if( style == "el" ){ m_style = EXTRA_LIGHT; }
		if( style == "eli" ){ m_style = EXTRA_LIGHT_ITALIC; }
		if( style == "l" ){ m_style = LIGHT; }
		if( style == "li" ){ m_style = LIGHT_ITALIC; }
		if( style == "r" ){ m_style = REGULAR; }
		if( style == "ri" ){ m_style = REGULAR_ITALIC; }
		if( style == "m" ){ m_style = MEDIUM; }
		if( style == "mi" ){ m_style = MEDIUM_ITALIC; }
		if( style == "sb" ){ m_style = SEMI_BOLD; }
		if( style == "sbi" ){ m_style = SEMI_BOLD_ITALIC; }
		if( style == "b" ){ m_style = BOLD; }
		if( style == "bi" ){ m_style = BOLD_ITALIC; }
		if( style == "eb" ){ m_style = EXTRA_BOLD; }
		if( style == "ebi" ){ m_style = EXTRA_BOLD_ITALIC; }
		printf("Font is %s %d %d\n", m_name.cstring(), m_point_size, m_style);
	}
}

int FontInfo::ascending_point_size(const void * a, const void * b){
	const FontInfo * info_a = (const FontInfo *)a;
	const FontInfo * info_b = (const FontInfo *)b;
	if( info_a->point_size() < info_b->point_size() ){ return -1; }
	if( info_b->point_size() < info_a->point_size() ){ return 1; }
	return 0;
}

int FontInfo::ascending_style(const void * a, const void * b){
	const FontInfo * info_a = (const FontInfo *)a;
	const FontInfo * info_b = (const FontInfo *)b;
	if( info_a->style() < info_b->style() ){ return -1; }
	if( info_b->style() < info_a->style() ){ return 1; }
	return 0;
}

const var::ConstString Font::m_ascii_character_set = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";

const var::ConstString & Font::ascii_character_set(){
	return m_ascii_character_set;
}

int Font::to_charset(char ascii){
	if( (ascii < ' ') || (ascii > '~') ){
		return -1;
	}
	return (int)(ascii - ' ' - 1);
}

Font::Font() {
	//m_bitmap = 0;
	m_offset = 0;
	m_space_size = 8;
	m_letter_spacing = 1;
}

int Font::calculate_length(const var::ConstString & str) const {
	u32 length = 0;
	const char * s = str.cstring();
	while( *s != 0 ){

		if( *s == ' ' ){
			length += space_size();
		} else {
			if( load_char(m_char, *s, true) == 0){
				length += m_char.advance_x;
			}
		}
		s++;
	}
	return length;
}

int Font::draw(char c, Bitmap & dest, const Point & point) const {

	if( load_char(m_char, c, true) < 0 ){
		return -1;
	}

	Point p = point + Point(m_char.offset_x, m_char.offset_y);

	draw_char_on_bitmap(m_char, dest, p);

	return m_char.advance_x;
}

int Font::draw(const var::ConstString & const_string, Bitmap & bitmap, const Point & point) const {
	char c;
	sg_size_t w;

	//draw characters on the bitmap
	Point p(point);
	u32 i = 0;
	while( (c = const_string.at(i++)) != 0){
		if( c == ' ' ){
			w = space_size();
		} else {
			draw(c, bitmap, p);
			w = m_char.advance_x;
		}

		//apply kerning
		w += load_kerning(c, const_string.at(i));

		if( w < 0 ){
			return -1;
		}

		p += Point(w,0);

	}
	return 0;
}

<commit_msg>fixes for fonts<commit_after>//Copyright 2011-2018 Tyler Gilbert; All Rights Reserved

#include <cstdio>
#include <errno.h>
#include "var/Token.hpp"
#include "sys/File.hpp"
#include "sgfx/Font.hpp"

using namespace sgfx;

FontInfo::FontInfo(u8 point_size, u8 style, const Font * font){
	m_point_size = point_size;
	m_style = style;
	m_font = font;
}

FontInfo::FontInfo(const var::ConstString & path){
	m_path = path;

	var::Tokenizer tokens(sys::File::name(path), "-.");

	if( tokens.count() != 4 ){
		m_point_size = 0;
	} else {

		m_font = 0;
		m_name = tokens.at(0);
		m_point_size = tokens.at(2).to_integer();
		var::String style = tokens.at(1);
		style.to_lower();

		m_style = ANY;
		if( style == "t" ){ m_style = THIN; }
		if( style == "ti" ){ m_style = THIN_ITALIC; }
		if( style == "el" ){ m_style = EXTRA_LIGHT; }
		if( style == "eli" ){ m_style = EXTRA_LIGHT_ITALIC; }
		if( style == "l" ){ m_style = LIGHT; }
		if( style == "li" ){ m_style = LIGHT_ITALIC; }
		if( style == "r" ){ m_style = REGULAR; }
		if( style == "ri" ){ m_style = REGULAR_ITALIC; }
		if( style == "m" ){ m_style = MEDIUM; }
		if( style == "mi" ){ m_style = MEDIUM_ITALIC; }
		if( style == "sb" ){ m_style = SEMI_BOLD; }
		if( style == "sbi" ){ m_style = SEMI_BOLD_ITALIC; }
		if( style == "b" ){ m_style = BOLD; }
		if( style == "bi" ){ m_style = BOLD_ITALIC; }
		if( style == "eb" ){ m_style = EXTRA_BOLD; }
		if( style == "ebi" ){ m_style = EXTRA_BOLD_ITALIC; }
	}
}

int FontInfo::ascending_point_size(const void * a, const void * b){
	const FontInfo * info_a = (const FontInfo *)a;
	const FontInfo * info_b = (const FontInfo *)b;
	if( info_a->point_size() < info_b->point_size() ){ return -1; }
	if( info_b->point_size() < info_a->point_size() ){ return 1; }
	return 0;
}

int FontInfo::ascending_style(const void * a, const void * b){
	const FontInfo * info_a = (const FontInfo *)a;
	const FontInfo * info_b = (const FontInfo *)b;
	if( info_a->style() < info_b->style() ){ return -1; }
	if( info_b->style() < info_a->style() ){ return 1; }
	return 0;
}

const var::ConstString Font::m_ascii_character_set = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";

const var::ConstString & Font::ascii_character_set(){
	return m_ascii_character_set;
}

int Font::to_charset(char ascii){
	if( (ascii < ' ') || (ascii > '~') ){
		return -1;
	}
	return (int)(ascii - ' ');
}

Font::Font() {
	//m_bitmap = 0;
	m_offset = 0;
	m_space_size = 8;
	m_letter_spacing = 1;
}

int Font::calculate_length(const var::ConstString & str) const {
	u32 length = 0;
	const char * s = str.cstring();
	while( *s != 0 ){

		if( *s == ' ' ){
			length += space_size();
		} else {
			if( load_char(m_char, *s, true) == 0){
				length += m_char.advance_x;
			}
		}
		s++;
	}
	return length;
}

int Font::draw(char c, Bitmap & dest, const Point & point) const {

	if( load_char(m_char, c, true) < 0 ){
		return -1;
	}

	Point p = point + Point(m_char.offset_x, m_char.offset_y);

	draw_char_on_bitmap(m_char, dest, p);

	return m_char.advance_x;
}

int Font::draw(const var::ConstString & const_string, Bitmap & bitmap, const Point & point) const {
	char c;
	sg_size_t w;

	//draw characters on the bitmap
	Point p(point);
	u32 i = 0;
	while( (c = const_string.at(i++)) != 0){
		if( c == ' ' ){
			w = space_size();
		} else {
			draw(c, bitmap, p);
			w = m_char.advance_x;
		}

		//apply kerning
		w += load_kerning(c, const_string.at(i));

		if( w < 0 ){
			return -1;
		}

		p += Point(w,0);

	}
	return 0;
}

<|endoftext|>