18cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/**
28cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @file diff_container.cpp
38cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Container for diffed symbols
48cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
58cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Copyright 2005 OProfile authors
68cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Read the file COPYING
78cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
88cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author Philippe Elie
98cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author John Levon
108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* older glibc has C99 INFINITY in _GNU_SOURCE */
138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#ifndef _GNU_SOURCE
148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define _GNU_SOURCE
158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#endif
168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "diff_container.h"
188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <cmath>
208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddusing namespace std;
228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddnamespace {
258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// a comparator suitable for diffing symbols
288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddbool rough_less(symbol_entry const & lhs, symbol_entry const & rhs)
298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (lhs.image_name != rhs.image_name)
318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return lhs.image_name < rhs.image_name;
328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (lhs.app_name != rhs.app_name)
348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return lhs.app_name < rhs.app_name;
358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (lhs.name != rhs.name)
378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return lhs.name < rhs.name;
388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return false;
408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// possibly add a diff sym
448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid
458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddadd_sym(diff_collection & syms, diff_symbol const & sym,
468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd        profile_container::symbol_choice & choice)
478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (choice.match_image
498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	    && (image_names.name(sym.image_name) != choice.image_name))
508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return;
518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (fabs(sym.diffs[0]) < choice.threshold)
538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return;
548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	choice.hints = sym.output_hint(choice.hints);
568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	syms.push_back(sym);
578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// add a symbol not present in the new profile
618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid
628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddsymbol_old(diff_collection & syms, symbol_entry const & sym,
638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd           profile_container::symbol_choice & choice)
648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	diff_symbol symbol(sym);
668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	symbol.diffs.fill(sym.sample.counts.size(), -INFINITY);
678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	add_sym(syms, symbol, choice);
688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// add a symbol not present in the old profile
728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid
738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddsymbol_new(diff_collection & syms, symbol_entry const & sym,
748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd           profile_container::symbol_choice & choice)
758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	diff_symbol symbol(sym);
778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	symbol.diffs.fill(sym.sample.counts.size(), INFINITY);
788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	add_sym(syms, symbol, choice);
798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// add a diffed symbol
838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid symbol_diff(diff_collection & syms,
848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd                 symbol_entry const & sym1, count_array_t const & total1,
858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd                 symbol_entry const & sym2, count_array_t const & total2,
868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd                 profile_container::symbol_choice & choice)
878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	diff_symbol symbol(sym2);
898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	size_t size = sym2.sample.counts.size();
918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (size_t i = 0; i != size; ++i) {
928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		double percent1;
938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		double percent2;
948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		percent1 = op_ratio(sym1.sample.counts[i], total1[i]);
958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		percent2 = op_ratio(sym2.sample.counts[i], total2[i]);
968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		symbol.diffs[i] = op_ratio(percent2 - percent1, percent1);
978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		symbol.diffs[i] *= 100.0;
988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	add_sym(syms, symbol, choice);
1018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}; // namespace anon
1058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodddiff_container::diff_container(profile_container const & c1,
1088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd                               profile_container const & c2)
1098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	: pc1(c1), pc2(c2),
1108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	  total1(pc1.samples_count()), total2(pc2.samples_count())
1118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodddiff_collection const
1168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodddiff_container::get_symbols(profile_container::symbol_choice & choice) const
1178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	diff_collection syms;
1198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/*
1218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * Do a pairwise comparison of the two symbol sets. We're
1228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * relying here on the symbol container being sorted such
1238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * that rough_less() is suitable for iterating through the
1248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * two lists (see less_symbol).
1258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 */
1268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	symbol_container::symbols_t::iterator it1 = pc1.begin_symbol();
1288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	symbol_container::symbols_t::iterator end1 = pc1.end_symbol();
1298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	symbol_container::symbols_t::iterator it2 = pc2.begin_symbol();
1308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	symbol_container::symbols_t::iterator end2 = pc2.end_symbol();
1318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	while (it1 != end1 && it2 != end2) {
1338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (rough_less(*it1, *it2)) {
1348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			symbol_old(syms, *it1, choice);
1358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			++it1;
1368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		} else if (rough_less(*it2, *it1)) {
1378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			symbol_new(syms, *it2, choice);
1388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			++it2;
1398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		} else {
1408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			symbol_diff(syms, *it1, total1, *it2, total2, choice);
1418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			++it1;
1428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			++it2;
1438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
1448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (; it1 != end1; ++it1)
1478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		symbol_old(syms, *it1, choice);
1488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (; it2 != end2; ++it2)
1508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		symbol_new(syms, *it2, choice);
1518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return syms;
1538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddcount_array_t const diff_container::samples_count() const
1578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return total2;
1598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
160