Example #1
0
bool IAddr_Func_EBPPrologue_UniqueStr::FindAddrWin(uintptr_t& addr) const
{
	using StrRefScanner = CTypeScanner<ScanDir::FORWARD, ScanResults::ALL, const char *>;
	
	const char *p_str = Scan::FindUniqueConstStr(this->GetLibrary(), this->GetUniqueStr());
	if (p_str == nullptr) {
		DevMsg("IAddr_Func_EBPPrologue_UniqueStr: \"%s\": failed to find ostensibly unique string\n", this->GetName());
		return false;
	}
	
	CScan<StrRefScanner> scan1(CLibSegBounds(this->GetLibrary(), Segment::TEXT), p_str);
	if (!scan1.ExactlyOneMatch()) {
		DevMsg("IAddr_Func_EBPPrologue_UniqueStr: \"%s\": found %u refs to ostensibly unique string\n", this->GetName(), scan1.Matches().size());
		return false;
	}
	auto p_in_func = (const char **)scan1.FirstMatch();
	
	auto p_func = Scan::FindFuncPrologue(p_in_func);
	if (p_func == nullptr) {
		DevMsg("IAddr_Func_EBPPrologue_UniqueStr: \"%s\": could not locate EBP prologue\n", this->GetName());
		return false;
	}
	
	addr = (uintptr_t)p_func;
	return true;
}
Example #2
0
Local void processUsual(struct LOC_processLine *LINK)
{
  if (hasVerseNumber(LINK->voice))
    strcat(LINK->pretex, "\\mtxVerse");
  LINK->l = pos1(multi_group, LINK->note);
  if (LINK->l > 0)
    scan1(LINK->note, LINK->l + 1, &LINK->nmulti);
  activateBeamsAndSlurs(LINK->voice);
  LINK->in_group = false;
  if (LINK->ngrace > 0) {
    LINK->in_group = true;
    LINK->ngrace--;
  } else {
    if (LINK->nmulti > 0) {
      LINK->in_group = true;
      LINK->nmulti--;
    }
  }
  checkOctave(LINK->voice, LINK->note);
  renewPitch(LINK->voice, LINK->note);
  if (!LINK->in_group) {
    resetDuration(LINK->voice, durationCode(LINK->note));
    markDebeamed(LINK->voice, LINK->note);
  }
  lookahead(LINK);
  getSyllable(LINK->voice, LINK->pretex);
  addUptext(LINK->voice, &LINK->no_uptext, LINK->pretex);
  addChords(LINK);
}
Example #3
0
bool IAddr_Func_EBPPrologue_UniqueRef::FindAddrWin(uintptr_t& addr) const
{
	using SymRefScanner = CTypeScanner<ScanDir::FORWARD, ScanResults::ALL, const void *>;
	
	auto p_ref = AddrManager::GetAddr(this->GetUniqueSymbol());
	if (p_ref == nullptr) {
		DevMsg("IAddr_Func_EBPPrologue_UniqueRef: \"%s\": no addr for ostensibly unique symbol\n", this->GetName());
		return false;
	}
	
	CScan<SymRefScanner> scan1(CLibSegBounds(this->GetLibrary(), Segment::TEXT), p_ref);
	if (!scan1.ExactlyOneMatch()) {
		DevMsg("IAddr_Func_EBPPrologue_UniqueRef: \"%s\": found %u refs to ostensibly unique symbol\n", this->GetName(), scan1.Matches().size());
		return false;
	}
	auto p_in_func = (const char **)scan1.FirstMatch();
	
	auto p_func = Scan::FindFuncPrologue(p_in_func);
	if (p_func == nullptr) {
		DevMsg("IAddr_Func_EBPPrologue_UniqueRef: \"%s\": could not locate EBP prologue\n", this->GetName());
		return false;
	}
	
	addr = (uintptr_t)p_func;
	return true;
}
Example #4
0
bool IAddr_Pattern::FindAddrWin(uintptr_t& addr) const
{
	using PatternScanner = CMaskedScanner<ScanDir::FORWARD, ScanResults::ALL, 1>;
	
	const char *str_seek = this->GetPattern();
	const char *str_mask = this->GetMask();
	
	size_t strlen_seek = strlen(str_seek);
	size_t strlen_mask = strlen(str_mask);
	
	if (strlen_seek == 0) {
		DevMsg("IAddr_Pattern: \"%s\": empty pattern\n", this->GetName());
		return false;
	}
	if (strlen_mask == 0) {
		DevMsg("IAddr_Pattern: \"%s\": empty mask\n", this->GetName());
		return false;
	}
	
	if (strlen_seek != strlen_mask) {
		DevMsg("IAddr_Pattern: \"%s\": pattern and mask have differing numbers of digits\n", this->GetName());
		return false;
	}
	
	if (strlen_seek % 2 == 1) {
		DevMsg("IAddr_Pattern: \"%s\": pattern and mask have odd number of digits\n", this->GetName());
		return false;
	}
	
	size_t len = strlen_seek / 2;
	
	ByteBuf seek(len);
	ByteBuf mask(len);
	
	for (size_t i = 0; i < len; ++i) {
		char buf[3];
		buf[2] = '\0';
		
		memcpy(buf, str_seek + (i * 2), 2);
		seek[i] = std::stoi(buf, nullptr, 0x10);
		
		memcpy(buf, str_mask + (i * 2), 2);
		mask[i] = std::stoi(buf, nullptr, 0x10);
	}
	
	CScan<PatternScanner> scan1(CLibSegBounds(this->GetLibrary(), LibMgr::Seg_FromString(this->GetSegment())), seek, mask);
	if (!scan1.ExactlyOneMatch()) {
		DevMsg("IAddr_Pattern: \"%s\": found %u pattern matches\n", this->GetName(), scan1.Matches().size());
		return false;
	}
	
	addr = (uintptr_t)scan1.FirstMatch();
	return true;
}
Example #5
0
void Hash_Partition(int *ary, int size)
{
	int *keyzonenum = (int*)malloc(sizeof(int) * size);
	assert(keyzonenum);
	memset(keyzonenum, 0, sizeof(int) * size);

	int *hisgram = (int*)malloc(sizeof(int) * ZONENUM);
	assert(hisgram);
	memset(hisgram, 0, sizeof(int) * ZONENUM);
	
	init(keyzonenum, size, ary);
	scan1(keyzonenum, hisgram, size);
	begin_addr(hisgram);
	scan2(keyzonenum, hisgram, size, ary);
			
	free(keyzonenum);
	free(hisgram);
}
Example #6
0
bool IAddr_DataDescMap::FindAddrWin(uintptr_t& addr) const
{
	struct GetDataDescMap {
		bool operator==(const GetDataDescMap& that) const { return (memcmp(this, &that, sizeof(*this)) == 0); }
		uint8_t buf[6];
	};
	
	using ClassNameRefScanner   = CTypeScanner<ScanDir::FORWARD, ScanResults::ALL, const char *,   0x4>;
	using GetDataDescMapScanner = CTypeScanner<ScanDir::FORWARD, ScanResults::ALL, GetDataDescMap, 0x10>;
	
	const char *p_str = Scan::FindUniqueConstStr(this->GetLibrary(), this->GetClassName());
	if (p_str == nullptr) {
		DevMsg("IAddr_DataDescMap: \"%s\": failed to find class name string\n", this->GetName());
		return false;
	}
	
	CScan<ClassNameRefScanner> scan1(CLibSegBounds(this->GetLibrary(), Segment::DATA), p_str);
	std::vector<GetDataDescMapScanner *> scanners;
	for (auto match : scan1.Matches()) {
		GetDataDescMap gddm;
		gddm.buf[0x00] = 0xb8; // mov eax,[????????]
		*(uint32_t *)(&gddm.buf[0x01]) = (uint32_t)match - offsetof(datamap_t, dataClassName);
		gddm.buf[0x05] = 0xc3; // ret
		
		scanners.push_back(new GetDataDescMapScanner(CLibSegBounds(this->GetLibrary(), Segment::TEXT), gddm));
	}
	
	CMultiScan<GetDataDescMapScanner> scan2(scanners);
	std::vector<const void *> results;
	for (auto scanner : scanners) {
		if (scanner->ExactlyOneMatch()) {
			results.push_back(scanner->FirstMatch());
		}
	}
	if (results.size() != 1) {
		DevMsg("IAddr_DataDescMap: \"%s\": found %u matches for GetDataDescMap func\n", this->GetName(), results.size());
		return false;
	}
	
	addr = *(uintptr_t *)((uintptr_t)results[0] + 1);
	return true;
}
Example #7
0
bool IAddr_Func_EBPPrologue_VProf::FindAddrWin(uintptr_t& addr) const
{
#if defined __GNUC__
#warning FIXME: VPROF_BUDGET finder is not reliable due to using first scan result
#endif
	using VProfScanner = CBasicScanner<ScanDir::FORWARD, ScanResults::FIRST, 1>;
	
	const char *p_name = Scan::FindUniqueConstStr(this->GetLibrary(), this->GetVProfName());
	if (p_name == nullptr) {
		DevMsg("IAddr_Func_EBPPrologue_VProf: \"%s\": failed to find name string\n", this->GetName());
		return false;
	}
	
	const char *p_group = Scan::FindUniqueConstStr(this->GetLibrary(), this->GetVProfGroup());
	if (p_group == nullptr) {
		DevMsg("IAddr_Func_EBPPrologue_VProf: \"%s\": failed to find group string\n", this->GetName());
		return false;
	}
	
	uint8_t vprof[] = {
		0x68, 0x00, 0x00, 0x00, 0x00, // push 0x????????
		0x68, 0x00, 0x00, 0x00, 0x00, // push 0x????????
	};
	*(const char **)(vprof + 0x01) = p_name;
	*(const char **)(vprof + 0x06) = p_group;
	CScan<VProfScanner> scan1(CLibSegBounds(this->GetLibrary(), Segment::TEXT), (const void *)vprof, sizeof(vprof));
	if (!scan1.ExactlyOneMatch()) {
		DevMsg("IAddr_Func_EBPPrologue_VProf: \"%s\": could not locate VPROF_BUDGET\n", this->GetName());
		return false;
	}
	auto p_in_func = scan1.FirstMatch();
	
	auto p_func = Scan::FindFuncPrologue(p_in_func);
	if (p_func == nullptr) {
		DevMsg("IAddr_Func_EBPPrologue_VProf: \"%s\": could not locate EBP prologue\n", this->GetName());
		return false;
	}
	
	addr = (uintptr_t)p_func;
	return true;
}
Example #8
0
bool IAddr_Func_EBPPrologue_NonUniqueStr_KnownVTIdx::FindAddrWin(uintptr_t& addr) const
{
	using StrRefScanner = CTypeScanner<ScanDir::FORWARD, ScanResults::ALL, const char *>;
	
	const char *p_str = Scan::FindUniqueConstStr(this->GetLibrary(), this->GetStr());
	if (p_str == nullptr) {
		DevMsg("IAddr_Func_EBPPrologue_NonUniqueStr_KnownVTIdx: \"%s\": failed to find string\n", this->GetName());
		return false;
	}
	
	CScan<StrRefScanner> scan1(CLibSegBounds(this->GetLibrary(), Segment::TEXT), p_str);
	if (scan1.Matches().empty()) {
		DevMsg("IAddr_Func_EBPPrologue_NonUniqueStr_KnownVTIdx: \"%s\": no refs to string\n", this->GetName());
		return false;
	}
	
	auto p_VT = RTTI::GetVTable(this->GetVTableName());
	if (p_VT == nullptr) {
		DevMsg("IAddr_Func_EBPPrologue_NonUniqueStr_KnownVTIdx: \"%s\": no addr for vtable\n", this->GetName());
		return false;
	}
	
	for (auto p_in_func : scan1.Matches()) {
		auto p_func = Scan::FindFuncPrologue(p_in_func);
		if (p_func == nullptr) {
			continue;
		}
		
		auto vfptr = p_VT[this->GetVTableIndex()];
		if (vfptr == p_func) {
			addr = (uintptr_t)p_func;
			return true;
		}
	}
	
	DevMsg("IAddr_Func_EBPPrologue_NonUniqueStr_KnownVTIdx: \"%s\": found %u string refs, but none matched vtable entry\n", this->GetName(), scan1.Matches().size());
	return false;
}
Example #9
0
bool IAddr_Func_EBPPrologue_UniqueStr_KnownVTIdx::FindAddrWin(uintptr_t& addr) const
{
	using StrRefScanner = CTypeScanner<ScanDir::FORWARD, ScanResults::ALL, const char *>;
	
	const char *p_str = Scan::FindUniqueConstStr(this->GetLibrary(), this->GetUniqueStr());
	if (p_str == nullptr) {
		DevMsg("IAddr_Func_EBPPrologue_UniqueStr_KnownVTIdx: \"%s\": failed to find ostensibly unique string\n", this->GetName());
		return false;
	}
	
	CScan<StrRefScanner> scan1(CLibSegBounds(this->GetLibrary(), Segment::TEXT), p_str);
	if (!scan1.ExactlyOneMatch()) {
		DevMsg("IAddr_Func_EBPPrologue_UniqueStr_KnownVTIdx: \"%s\": found %u refs to ostensibly unique string\n", this->GetName(), scan1.Matches().size());
		return false;
	}
	auto p_in_func = (const char **)scan1.FirstMatch();
	
	auto p_func = Scan::FindFuncPrologue(p_in_func);
	if (p_func == nullptr) {
		DevMsg("IAddr_Func_EBPPrologue_UniqueStr_KnownVTIdx: \"%s\": could not locate EBP prologue\n", this->GetName());
		return false;
	}
	
	auto p_VT = RTTI::GetVTable(this->GetVTableName());
	if (p_VT == nullptr) {
		DevMsg("IAddr_Func_EBPPrologue_UniqueStr_KnownVTIdx: \"%s\": no addr for vtable\n", this->GetName());
		return false;
	}
	
	auto vfptr = p_VT[this->GetVTableIndex()];
	if (vfptr != p_func) {
		DevMsg("IAddr_Func_EBPPrologue_UniqueStr_KnownVTIdx: \"%s\": func addr (0x%08x) doesn't match vtable entry (0x%08x)\n", this->GetName(), (uintptr_t)p_func, (uintptr_t)vfptr);
		return false;
	}
	
	addr = (uintptr_t)p_func;
	return true;
}
Example #10
0
Static void processLine(voice_index voice_, short bar_no)
{
  struct LOC_processLine V;
  paragraph_index par_line;
  Char STR1[256];

  V.voice = voice_;
  *V.pretex = '\0';
  V.no_chords = false;
  V.no_uptext = false;
  par_line = musicLineNo(V.voice);
  V.nmulti = 0;
  V.ngrace = 0;
  line_no = orig_line_no[par_line-1];
  do {
    getMusicWord(V.note, V.voice);
    if (*V.note == '\0')
      return;
    /* if debugMode then writeln(voice,' ',note); */
    switch (thisNote(V.voice)) {

    case rword:
      if (*multi_bar_rest != '\0') {
	if (uptextOnRests())
	  addUptext(V.voice, &V.no_uptext, V.pretex);
      } else {
	V.l = pos1(multi_group, V.note);
	if (V.l > 0)
	  scan1(V.note, V.l + 1, &V.nmulti);
	if (V.nmulti > 0) {
	  V.in_group = true;
	  V.nmulti--;
	}
	if (uptextOnRests())
	  addUptext(V.voice, &V.no_uptext, V.pretex);
	if (!(isPause(V.note) || V.in_group))
	      /*0.63: allow rests in xtuples*/
		resetDuration(V.voice, durationCode(V.note));
      }
      break;

    case abcdefg:
      processUsual(&V);
      break;

    case barword:
      if (V.voice == nvoices) {
	if (endOfBar(V.voice, bar_no))
	  strcpy(repeat_sign, V.note);
	else
	  writeRepeat(V.note);
      }
      sprintf(STR1, "%c", barsym);
      if (strcmp(V.note, STR1))
	*V.note = '\0';
      V.no_chords = false;
      break;

    case FirstOnly:
      if (V.voice != nvoices)
	*V.note = '\0';
      else
	strcpy(V.note, processOther(STR1, V.note, &V));
      break;

    default:
      strcpy(V.note, processOther(STR1, V.note, &V));
      break;
    }
    output(V.note, &V);
  } while (!endOfBar(V.voice, bar_no));
  if (!V.no_chords)
    skipChordBar(V.voice);
}
int main(int argc, char * argv[])
{
    if (argc != 3)
    {
        std::cerr << "ERROR: Wrong number of arguments." << std::endl;
        std::cout << "Usage:\n\t" << argv[0] << " file1 file2" << std::endl;

        return 1;
    }

    std::ifstream
        file1(argv[1], std::ios_base::binary | std::ios_base::in),
        file2(argv[2], std::ios_base::binary | std::ios_base::in);

    if (!file1 || !file2)
    {
        std::cerr << "ERROR: Unable to open one or both files." << std::endl;
        return 2;
    }

    file1.unsetf(std::ios_base::skipws);
    file2.unsetf(std::ios_base::skipws);

    iterator
        iter_file1(file1),
        iter_file2(file2);

    scanner
        scan1(iter_file1, iterator()),
        scan2(iter_file2, iterator());

    std::size_t line = 1, column = 1;

    while (!scan1.at_end() && !scan2.at_end())
    {
        if (spirit::eol_p.parse(scan1))
        {
            if (!spirit::eol_p.parse(scan2))
            {
                std::cout << "Files differ at line " << line << ", column " <<
                    column << '.' << std::endl;
                return 3;
            }

            ++line, column = 1;
            continue;
        }

        if (*scan1 != *scan2)
        {
            std::cout << "Files differ at line " << line << ", column " <<
                column << '.' << std::endl;
            return 4;
        }

        ++scan1, ++scan2, ++column;
    }

    if (scan1.at_end() != scan2.at_end())
    {
        std::cout << "Files differ in length." << std::endl;
        return 5;
    }
}
Example #12
0
void match(
	int N, // number of nodes (must be even)
	double *total_weight, // cost of optimal matching
	int *nmatch, // matching array
	double (*cost)(int i, int j, void* data), void *data,
	// The following are work arrays each of length N
	int *basis,
	int *mem,
	int *ka,
	int *kb,
	int *sm,
	int *tma,
	int *tmb,
	int *m1,
	double *y1,
	double *y2,
	double *dplus,
	double *dminus
){
	const int top = N + 1;
	for(int n1 = 0; n1 < N; ++n1){
		basis[n1] = n1;
		mem[n1] = n1;
		y1[n1] = 0.0;
		y2[n1] = 0.0;
		sm[n1] = top;
		tma[n1] = top;
		tmb[n1] = top;
		nmatch[n1] = top;
		dplus[n1] = DBL_MAX;
		dminus[n1] = DBL_MAX;
		ka[n1] = -1;
		kb[n1] = n1;
	}

	// Start of main procedure
	for(int n1 = 0; n1 < N; ++n1){
		if(nmatch[n1] != top){ continue; }
		int nn = -1;
		double d = DBL_MAX;
		for(int n2 = 0; n2 < N; ++n2) {
			if(n1 == n2){ continue; }
			double newcost = cost(n1,n2,data) - y1[n2];
			if(newcost < d){
				d = newcost;
				nn = -1;
				if(nmatch[n2] == top){
					nn = n2;
				}
			}else if(newcost == d && nn < 0 && nmatch[n2] == top){
				nn = n2;
			}
		}
		if(nn >= 0){
			y1[n1] = d;
			nmatch[n1] = nn;
			nmatch[nn] = n1;
		}
	}
	

	// Initial labeling
	int nn = 0;
	for(int ni = 0; ni < N; ++ni){
		if(nmatch[ni] != top){ continue; }
		nn++;
		sm[ni] = -1;
		dplus[ni] = 0.0;
		double Y1B = y1[ni];
		for(int nk = 0; nk < N; ++nk){
			if(ni == nk){ continue; }
			double newcost = cost(ni,nk,data) - Y1B - y1[nk];
			if(newcost < dminus[nk]){
				dminus[nk] = newcost;
				ka[nk] = ni;
			}
		}
	}
	if(nn <= 1){ goto finalize; }

	// Examination of the labeling and decision for the next step
	{
make_decision:
		int n1, n2;
		int nka, nkb;
		double dbest = DBL_MAX;
		int nbest;
		for(int nb = 0; nb < N; ++nb) {
			if(basis[nb] != nb){ continue; }
			double d = dminus[nb];
			if(sm[nb] >=  top){
				if(tma[nb] >= top){
					if(d >= dbest){ continue; }
					nbest = nb;
					dbest = d;
				}
				if(mem[nb] != nb){
					d += y1[nb];
					if(d < dbest){
						nbest = nb;
						dbest = d;
					}
				}
			}else{
				d = 0.5*(d + dplus[nb]);
				if(d <= dbest){
					nbest = nb;
					dbest = d;
				}
			}
		}

		if(tma[nbest] < top){
			// Expansion of a T labeled blossom
			n1 = mem[nbest];
			int nb3 = n1;
			nka = ka[n1];
			{
				int nk2 = n1;
				do{
					int nk1 = nk2;
					nkb = kb[nk1];
					double y1b = y1[nk1];

					do{
						basis[nk2] = nk1;
						y2[nk2] -= y1b;
						if(nk2 == nkb){ break; }
						nk2 = mem[nk2];
					}while(1);
					nk2 = mem[nkb];
					mem[nkb] = nk1;
				}while(nk2 != nka);
			}
			{
				double y1b = dplus[n1];
				y1[nbest] = y1b;
				mem[nbest] = nka;
				int nk2 = nka;
				do{
					y2[nk2] -= y1b;
					if(nk2 == nbest){ break; }
					nk2 = mem[nk2];
				}while(1);
			}

			int nk1 = nmatch[nbest];
			int nb = basis[sm[basis[nk1]]];
			if(nb != nbest){
				{
					int nb2 = nb;
					int nk;
					do{
						nk = tma[nb2];
						int nb1 = basis[nk];
						if(nb1 == nbest){break; }
						nb2 = sm[nb1];
						nb2 = basis[nb2];
					}while(1);

					tma[nb] = tma[nbest];
					tma[nbest] = tmb[nb2];
					tmb[nb] = tmb[nbest];
					tmb[nbest] = nk;
				}
				int nk3 = sm[nb];
				nb3 = basis[nk3];
				int nk4 = sm[nb3];
				sm[nb] = top;
				nmatch[nb] = nk1;
				int nb1 = nb3;
				do{
					nk1 = tma[nb1];
					int nk2 = tmb[nb1];
					tma[nb1] = nk4;
					tmb[nb1] = nk3;
					sm[nb1] = nk1;
					nmatch[nb1] = nk1;
					int nb2 = basis[nk1];
					nmatch[nb2] = nk2;
					nk3 = sm[nb2];
					sm[nb2] = nk2;
					if(nb2 == nbest){ break; }
					nb1 = basis[nk3];
					nk4 = sm[nb1];
					tma[nb2] = nk3;
					tmb[nb2] = nk4;
				}while(1);
			}
			int nk2 = tmb[nb];
			int nb1 = basis[nk2];
			dminus[nb1] = dbest;
			n1 = -1;
			if(nb1 != nb){
				nk1 = tma[nb1];
				nb3 = basis[nk1];
				tma[nb1] = tma[nb];
				tmb[nb1] = nk2;

				int nk;
				do{
					nk = sm[nb1];
					sm[nb1] = top;
					int nb2 = basis[nk];
					nk = tma[nb2];
					tma[nb2] = top;
					n2 = tmb[nb2];
					tmb[nb2] = n1;
					n1 = nb2;
					dplus[nb2] = dbest;
					nb1 = basis[nk];
					dminus[nb1] = dbest;
				}while(nb1 != nb);
				tma[nb] = n2;
				tmb[nb] = nk;
				sm[nb] = top;

				if(nb3 == nb){ goto do_scan1; }
			}
			nb1 = -1;
			{
				int nb2 = nb3;
				do{
					int nk = sm[nb2];
					sm[nb2] = top;
					tma[nb2] = top;
					tmb[nb2] = nb1;
					nb1 = basis[nk];
					
					nk = tma[nb1];
					sm[nb1] = top;
					tma[nb1] = top;
					tmb[nb1] = nb2;
					nb2 = basis[nk];
				}while(nb2 != nb);
			}

			scan2(nb1, N, cost, data, basis, mem, ka, kb, sm, tma, tmb,
				y1, y2, dplus, dminus);
do_scan1:
			while(n1 >= 0){
				int nb = n1;

				scan1(nb, N, cost, data, basis, mem, ka, kb, sm, tma, tmb,
					y1, y2, dplus, dminus, m1);

				n1 = tmb[nb];
				tmb[nb] = top;
			}
		}else if(sm[nbest] >= top){
			// Growing an alternating tree by adding two edges

			tma[nbest] = ka[nbest];
			tmb[nbest] = kb[nbest];
			int nmb = basis[nmatch[nbest]];
			dplus[nmb] = dbest;
			sm[nmb] = nmatch[nmb];

			scan1(nmb, N, cost, data, basis, mem, ka, kb, sm, tma, tmb,
				y1, y2, dplus, dminus, m1);
		}else{
			nka = ka[nbest];
			nkb = kb[nbest];
			n1 = nbest;
			int nb1 = n1;
			n2 = basis[nka];
			int nb2 = n2;
			do{
				tma[nb1] = nb2;
				int nk = sm[nb1];
				if(nk < 0){ break; }
				nb2 = basis[nk];
				nb1 = tma[nb2];
				nb1 = basis[nb1];
			}while(1);
			int nb = nb1;
			nb1 = n2;
			nb2 = n1;
			while(tma[nb1] >= top){
				tma[nb1] = nb2;
				int nk = sm[nb1];
				if(nk < 0){ goto augment_matching; }
				nb2 = basis[nk];
				nb1 = tma[nb2];
				nb1 = basis[nb1];
			}
			while(nb1 != nb){
				int nk = tma[nb];
				tma[nb] = top;
				nb = basis[nmatch[nk]];
			}
			
			// Shinking a blossom
			double yb = y1[nb] + dbest - dplus[nb];
			y1[nb] = 0.0;
			int nk1 = nb;
			do{
				y2[nk1] += yb;
				nk1 = mem[nk1];
			}while(nk1 != nb);
			int memsave = mem[nb];
			if(nb == n2){
				n2 = n1;
				nb2 = tma[nb];
			}
			do{
				mem[nk1] = nb2;
				int nm = nmatch[nb2];
				sm[nb2] = nm;
				double y1b = y1[nb2] + dminus[nb2] - dbest;
				nk1 = nb2;
				int nk2;
				do{
					nk2 = nk1;
					y2[nk2] += y1b;
					basis[nk2] = nb;
					nk1 = mem[nk2];
				}while(nk1 != nb2);
				kb[nb2] = nk2;
				y1[nb2] = y1b;
				nb1 = basis[nm];
				mem[nk2] = nb1;
				y1b = y1[nb1] + dbest - dplus[nb1];
				nk2 = nb1;

				do{
					nk1 = nk2;
					y2[nk1] += y1b;
					basis[nk1] = nb;
					nk2 = mem[nk1];
				}while(nk2 != nb1);
				kb[nb1] = nk1;
				y1[nb1] = y1b;
				if(n2 != nb1){
					nb2 = tma[nb1];
					tma[nb1] = tmb[nb2];
					tmb[nb1] = tma[nb2];
					continue;
				}
				
				if(n2 != nbest){
					tma[n2] = nkb;
					tmb[n2] = nka;
					if(nb != nbest){
						n2 = n1;
						nb2 = tma[nb];
						continue;
					}
					break;
				}else{
					tma[nbest] = nka;
					tmb[nbest] = nkb;
					break;
				}
			}while(1);

			mem[nk1] = memsave;
			n1 = mem[nb];
			ka[n1] = memsave;
			dplus[n1] = yb;
			tma[nb] = top;
			dplus[nb] = dbest;

			scan1(nb, N, cost, data, basis, mem, ka, kb, sm, tma, tmb,
				y1, y2, dplus, dminus, m1);
		}
		goto make_decision;

		// Augmentation of matching
		// Exchange of the matching and non matching edges along the augmenting path
augment_matching:
		{
			int nb = n1;
			int nk = nka;
			do{
				int nb1 = nb;
				do{
					nmatch[nb1] = nk;
					nk = sm[nb1];
					tma[nb1] = top;
					if(nk < 0){ break; }
					int nb2 = basis[nk];
					int nk1 = tma[nb2];
					nk = tmb[nb2];
					nb1 = basis[nk1];
					nmatch[nb2] = nk1;
				}while(1);
				if(nb != n1){ break; }
				nb = n2;
				nk = nkb;
			}while(1);
		}

		// Removing all labels on non exposed base nodes
		for(int nb = 0; nb < N; ++nb){
			if(basis[nb] != nb){ continue; }
			if(sm[nb] >= top){
				if(tma[nb] < top){
					double d = dminus[nb] - dbest;
					y1[nb] += d;
					tma[nb] = top;
					tmb[nb] = top;
				}
			}else{
				double d = dbest - dplus[nb];
				y1[nb] += d;
				sm[nb] = top;
				if(nmatch[nb] != top){
					dplus[nb] = DBL_MAX;
				}else{
					sm[nb] = -1;
					dplus[nb] = 0.0;
				}
			}
			dminus[nb] = DBL_MAX;
		}
		nn -= 2;
		if(nn <= 1){ goto finalize; }

		// Determination of the new dminus values
		for(int n1 = 0; n1 < N; ++n1){
			int nb1 = basis[n1];
			if(sm[nb1] >= 0){ continue; }
			double y1b = y1[nb1];
			double y2b = y2[n1];

			for(int n2 = 0; n2 < N; ++n2) {
				int nb2 = basis[n2];
				if(nb1 == nb2){ continue; }
				if(n1 == n2){ continue; }
				double newcost = cost(n1,n2,data) - y1b - y2b - y1[nb2] - y2[n2];
				if(newcost < dminus[nb2]){
					ka[nb2] = n1;
					kb[nb2] = n2;
					dminus[nb2] = newcost;
				}
			}
		}
		goto make_decision;
	}
	// Generation of the original graph by expansion of all shrunken blossoms
finalize:

	*total_weight = 0;
	for(int nb1 = 0; nb1 < N; ++nb1) {
		if(basis[nb1] != nb1 || sm[nb1] < -1){ continue; }
		int n2 = nmatch[nb1];
		int nb2 = basis[n2];
		int n1 = nmatch[nb2];
		sm[nb1] = -2;
		sm[nb2] = -2;
		if(n1 == n2){ continue; }
		double nc = cost(n1,n2,data);
		//double d = nc - y1[nb1] - y1[nb2] - y2[n1] - y2[n2];
		*total_weight += nc;
	}
	for(int n1 = 0; n1 < N; ++n1) {
restart_loop:
		int nb = basis[n1];
		if(nb == n1){ continue; }
		int nk2 = mem[nb];
		int nka = ka[nk2];
		int nb3 = nk2;
		double yb = dplus[nk2];
		do{
			int nk1 = nk2;
			int nkb = kb[nk1];
			double y1b = y1[nk1];
			do{
				basis[nk2] = nk1;
				y2[nk2] -= y1b;
				if(nk2 == nkb){ break;}
				nk2 = mem[nk2];
			}while(1);
			nk2 = mem[nkb];
			mem[nkb] = nk1;
		}while(nk2 != nka);
		y1[nb] = yb;
		mem[nb] = nka;
		nk2 = nka;
		do{
			y2[nk2] -= yb;
			if(nk2 == nb){ break; }
			nk2 = mem[nk2];
		}while(1);

		int nk = nmatch[nb];
		int nk1 = basis[nk];
		nk1 = nmatch[nk1];
		int nb1 = basis[nk1];
		if(nb == nb1){
			goto skip_forward;
		}
		nmatch[nb1] = nk;
		nb3 = tma[nb1];
		nb3 = basis[nb3];
		do{
			int nb2 = basis[sm[nb1]];
			int nk1 = tma[nb2];
			nk2 = tmb[nb2];
			nb1 = basis[nk1];
			nmatch[nb1] = nk2;
			nmatch[nb2] = nk1;
			if(nk1 == nk2){
				goto restart_loop;
			}
			double nc = cost(nk1,nk2,data);
			double d = nc - y1[nb1] - y1[nb2] - y2[nk1] - y2[nk2];

			if(fabs(d) > DBL_EPSILON){
				fprintf(stderr,
					"Optimality conditions are violated at edge %3d <--> %3d)\n",
					nk1, nk2);
			}

			*total_weight += nc;
		}while(nb1 != nb);
loop:
		if(nb3 == nb)  goto restart_loop;
skip_forward:
		int n2 = sm[nb3];
		int nb2 = basis[n2];
		int n3 = sm[nb2];
		if(n2 == n3){ goto restart_loop; }
		
		{
			double nc = cost(n2,n3,data);
			double d = nc - y1[nb2] - y1[nb3] - y2[n2] - y2[n3];

			if(fabs(d) > DBL_EPSILON){
				fprintf(stderr,
					"Optimality conditions are violated at edge %3d <--> %3d)\n",
					n2, n3);
			}

			*total_weight += nc;
		}
		n3 = tma[nb2];
		nb3 = basis[n3];
		goto loop;
	}
}