summaryrefslogtreecommitdiffstats
path: root/src/parameters
diff options
context:
space:
mode:
Diffstat (limited to 'src/parameters')
-rw-r--r--src/parameters/learn.cpp282
-rw-r--r--src/parameters/parameters.cpp462
-rw-r--r--src/parameters/parameters.h123
-rw-r--r--src/parameters/persistent.cpp202
4 files changed, 1069 insertions, 0 deletions
diff --git a/src/parameters/learn.cpp b/src/parameters/learn.cpp
new file mode 100644
index 0000000..aaef5a2
--- /dev/null
+++ b/src/parameters/learn.cpp
@@ -0,0 +1,282 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include "parameters.h"
+#include "../measurement/measurement.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+extern int debug_learning;
+
+double calculate_params(struct parameter_bundle *params)
+{
+ unsigned int i;
+
+ params->score = 0;
+
+
+ for (i = 0; i < past_results.size(); i++)
+ compute_bundle(params, past_results[i]);
+
+ return params->score;
+}
+
+
+/*
+ * gradual linear convergence of non-independent variables works better if once in a while
+ * you make a wrong move....
+ */
+static int random_disturb(int retry_left)
+{
+ if (retry_left < 10)
+ return 0;
+
+ if ( (rand() % 500) == 7)
+ return 1;
+ return 0;
+}
+
+static int try_zero(double value)
+{
+ if (value > 0.01)
+ if ( (rand() % 100) == 1)
+ return 1;
+
+ if ( (rand() % 5) == 1)
+ return 1;
+ return 0;
+}
+
+static unsigned int previous_measurements;
+
+static void weed_empties(struct parameter_bundle *best_so_far)
+{
+ double best_score;
+ unsigned int i;
+
+ best_score = best_so_far->score;
+
+
+ for (i = 0; i < best_so_far->parameters.size(); i++) {
+ double orgvalue;
+
+ orgvalue = best_so_far->parameters[i];
+
+
+ best_so_far->parameters[i] = 0.0;
+
+ calculate_params(best_so_far);
+ if (best_so_far->score > best_score) {
+ best_so_far->parameters[i] = orgvalue;
+ } else {
+ best_score = best_so_far->score;
+ }
+
+ }
+ calculate_params(best_so_far);
+
+}
+
+/* leaks like a sieve */
+void learn_parameters(int iterations, int do_base_power)
+{
+ struct parameter_bundle *best_so_far;
+ double best_score = 10000000000000000.0;
+ int retry = iterations;
+ int prevparam = -1;
+ int locked = 0;
+ static unsigned int bpi = 0;
+ unsigned int i;
+ time_t start;
+
+ /* don't start fitting anything until we have at least 1 more measurement than we have parameters */
+ if (past_results.size() <= all_parameters.parameters.size())
+ return;
+
+
+
+// if (past_results.size() == previous_measurements)
+// return;
+
+ precompute_valid();
+
+
+ previous_measurements = past_results.size();
+
+ double delta = 0.50;
+
+ best_so_far = &all_parameters;
+
+ if (!bpi)
+ bpi = get_param_index("base power");
+
+ calculate_params(best_so_far);
+ best_score = best_so_far->score;
+
+ delta = 0.001 / pow(0.8, iterations / 2.0);
+ if (iterations < 25)
+ delta = 0.001 / pow(0.5, iterations / 2.0);
+
+ if (delta > 0.2)
+ delta = 0.2;
+
+ if (1.0 * best_score / past_results.size() < 4 && delta > 0.05)
+ delta = 0.05;
+
+ if (debug_learning)
+ printf("Delta starts at %5.3f\n", delta);
+
+ if (best_so_far->parameters[bpi] > min_power * 0.9)
+ best_so_far->parameters[bpi] = min_power * 0.9;
+
+ /* We want to give up a little of base power, to give other parameters room to change;
+ base power is the end post for everything after all
+ */
+ if (do_base_power && !debug_learning)
+ best_so_far->parameters[bpi] = best_so_far->parameters[bpi] * 0.9998;
+
+ start = time(NULL);
+
+ while (retry--) {
+ int changed = 0;
+ int bestparam;
+ double newvalue = 0;
+ double orgscore;
+ double weight;
+
+ bestparam = -1;
+
+ if (time(NULL) - start > 1 && !debug_learning)
+ retry = 0;
+
+ calculate_params(best_so_far);
+ orgscore = best_score = best_so_far->score;
+
+
+ for (i = 1; i < best_so_far->parameters.size(); i++) {
+ double value, orgvalue;
+
+ weight = delta * best_so_far->weights[i];
+
+ orgvalue = value = best_so_far->parameters[i];
+ if (value <= 0.001) {
+ value = 0.1;
+ } else
+ value = value * (1 + weight);
+
+ if (i == bpi && value > min_power)
+ value = min_power;
+
+ if (i == bpi && orgvalue > min_power)
+ orgvalue = min_power;
+
+ if (value > 5000)
+ value = 5000;
+
+// printf("Trying %s %4.2f -> %4.2f\n", param.c_str(), best_so_far->parameters[param], value);
+ best_so_far->parameters[i] = value;
+
+ calculate_params(best_so_far);
+ if (best_so_far->score < best_score || random_disturb(retry)) {
+ best_score = best_so_far->score;
+ newvalue = value;
+ bestparam = i;
+ changed++;
+ }
+
+ value = orgvalue * 1 / (1 + weight);
+
+ if (value < 0.0001)
+ value = 0.0;
+
+ if (try_zero(value))
+ value = 0.0;
+
+
+ if (value > 5000)
+ value = 5000;
+
+
+// printf("Trying %s %4.2f -> %4.2f\n", param.c_str(), orgvalue, value);
+
+ if (orgvalue != value) {
+ best_so_far->parameters[i] = value;
+
+ calculate_params(best_so_far);
+
+ if (best_so_far->score + 0.00001 < best_score || (random_disturb(retry) && value > 0.0)) {
+ best_score = best_so_far->score;
+ newvalue = value;
+ bestparam = i;
+ changed++;
+ }
+ }
+ best_so_far->parameters[i] = orgvalue;
+
+ }
+ if (!changed) {
+ double mult;
+
+ if (!locked) {
+ mult = 0.8;
+ if (iterations < 25)
+ mult = 0.5;
+ delta = delta * mult;
+ }
+ locked = 0;
+ prevparam = -1;
+ } else {
+ if (debug_learning) {
+ printf("Retry is %i \n", retry);
+ printf("delta is %5.4f\n", delta);
+ printf("Best parameter is %i \n", bestparam);
+ printf("Changing score from %4.3f to %4.3f\n", orgscore, best_score);
+ printf("Changing value from %4.3f to %4.3f\n", best_so_far->parameters[bestparam], newvalue);
+ }
+ best_so_far->parameters[bestparam] = newvalue;
+ if (prevparam == bestparam)
+ delta = delta * 1.1;
+ prevparam = bestparam;
+ locked = 1;
+ }
+
+ if (delta < 0.001 && !locked)
+ break;
+
+ if (retry % 50 == 49)
+ weed_empties(best_so_far);
+ }
+
+
+ /* now we weed out all parameters that don't have value */
+ if (iterations > 50)
+ weed_empties(best_so_far);
+
+ if (debug_learning)
+ printf("Final score %4.2f (%i points)\n", best_so_far->score / past_results.size(), (int)past_results.size());
+// dump_parameter_bundle(best_so_far);
+// dump_past_results();
+}
diff --git a/src/parameters/parameters.cpp b/src/parameters/parameters.cpp
new file mode 100644
index 0000000..38e1752
--- /dev/null
+++ b/src/parameters/parameters.cpp
@@ -0,0 +1,462 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include "parameters.h"
+#include "../measurement/measurement.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <vector>
+#include <unistd.h>
+#include <limits.h>
+
+
+struct parameter_bundle all_parameters;
+struct result_bundle all_results;
+
+vector <struct result_bundle *> past_results;
+
+map <string, int> param_index;
+static int maxindex = 1;
+map <string, int> result_index;
+static int maxresindex = 1;
+
+int get_param_index(const char *name)
+{
+ std::map<string, int>::iterator it;
+ int index = 0;
+
+ it = param_index.find(name);
+ if (it == param_index.end()) {
+ param_index[name] = ++maxindex;
+ index = maxindex;
+ } else
+ index = it->second;
+
+ if (index == 0)
+ printf("OH BLA\n");
+ return index;
+}
+
+int get_result_index(const char *name)
+{
+ std::map<string, int>::iterator it;
+ int index = 0;
+
+ it = result_index.find(name);
+ if (it == result_index.end()) {
+ result_index[name] = ++maxresindex;
+ index = maxresindex;
+ } else
+ index = it->second;
+
+ return index;
+}
+
+
+void register_parameter(const char *name, double default_value, double weight)
+{
+ int index;
+
+ index = get_param_index(name);
+
+ if (index >= (int)all_parameters.parameters.size()) {
+ all_parameters.parameters.resize(index+1, 0.0);
+ all_parameters.weights.resize(index+1, 1.0);
+ }
+
+ if (all_parameters.parameters[index] <= 0.0001)
+ all_parameters.parameters[index] = default_value;
+
+ all_parameters.weights[index] = weight;
+}
+
+void set_parameter_value(const char *name, double value, struct parameter_bundle *bundle)
+{
+ int index;
+
+ index = get_param_index(name);
+
+ if (index >= (int)bundle->parameters.size()) {
+ bundle->parameters.resize(index+1, 0.0);
+ bundle->weights.resize(index+1, 1.0);
+ }
+
+ bundle->parameters[index] = value;
+}
+
+double get_parameter_value(const char *name, struct parameter_bundle *the_bundle)
+{
+ unsigned int index;
+ index = get_param_index(name);
+ return get_parameter_value(index, the_bundle);
+}
+
+double get_parameter_value(unsigned int index, struct parameter_bundle *the_bundle)
+{
+ if (index >= the_bundle->parameters.size()) {
+ fprintf(stderr, "BUG: requesting unregistered parameter %d\n", index);
+ return 0;
+ }
+ return the_bundle->parameters[index];
+}
+
+double get_parameter_weight(int index, struct parameter_bundle *the_bundle)
+{
+ return the_bundle->weights[index];
+}
+
+double get_result_value(const char *name, struct result_bundle *the_bundle)
+{
+ return get_result_value(get_result_index(name), the_bundle);
+}
+
+void set_result_value(const char *name, double value, struct result_bundle *the_bundle)
+{
+ unsigned int index = get_result_index(name);
+ if (index >= the_bundle->utilization.size())
+ the_bundle->utilization.resize(index+1);
+ the_bundle->utilization[index] = value;
+}
+
+void set_result_value(unsigned int index, double value, struct result_bundle *the_bundle)
+{
+ if (index >= the_bundle->utilization.size())
+ the_bundle->utilization.resize(index+1);
+ the_bundle->utilization[index] = value;
+}
+
+double get_result_value(int index, struct result_bundle *the_bundle)
+{
+ if (!the_bundle)
+ return 0;
+ if (index >= (int) the_bundle->utilization.size())
+ return 0;
+ return the_bundle->utilization[index];
+}
+
+
+int result_device_exists(const char *name)
+{
+ unsigned int i;
+ for (i = 0; i < all_devices.size(); i++) {
+ if (strcmp(all_devices[i]->device_name(), name) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+void report_utilization(const char *name, double value, struct result_bundle *bundle)
+{
+ set_result_value(name, value, bundle);
+}
+void report_utilization(int index, double value, struct result_bundle *bundle)
+{
+ set_result_value(index, value, bundle);
+}
+
+
+
+double compute_bundle(struct parameter_bundle *parameters, struct result_bundle *results)
+{
+ double power = 0;
+ unsigned int i;
+
+ static int bpi = 0;
+
+ if (!bpi)
+ bpi = get_param_index("base power");
+
+ for (i = 0; i < all_devices.size(); i++)
+ power += all_devices[i]->power_usage(results, parameters);
+
+ parameters->actual_power = results->power;
+ parameters->guessed_power = power;
+ /* scale the squared error by the actual power so that non-idle data points weigh heavier */
+ parameters->score += results->power * (power - results->power) * (power - results->power);
+ parameters->parameters[bpi] = power;
+ return power;
+}
+
+static int precomputed_valid = 0;
+void precompute_valid(void)
+{
+ unsigned int i;
+
+
+ for (i = 0; i < all_devices.size(); i++) {
+ all_devices[i]->cached_valid = all_devices[i]->power_valid();
+ }
+ precomputed_valid = 1;
+}
+
+double bundle_power(struct parameter_bundle *parameters, struct result_bundle *results)
+{
+ double power = 0;
+ unsigned int i;
+ static int bpi = 0;
+
+ if (!bpi)
+ bpi = get_param_index("base power");
+
+ if (!precomputed_valid)
+ precompute_valid();
+
+
+ power = parameters->parameters[bpi];
+
+ for (i = 0; i < all_devices.size(); i++) {
+
+ if (all_devices[i]->cached_valid)
+ power += all_devices[i]->power_usage(results, parameters);
+ }
+
+ return power;
+}
+
+
+void dump_parameter_bundle(struct parameter_bundle *para)
+{
+ map<string, int>::iterator it;
+ int index;
+
+ printf("\n\n");
+ printf("Parameter state \n");
+ printf("----------------------------------\n");
+ printf("Value\t\tName\n");
+ for (it = param_index.begin(); it != param_index.end(); it++) {
+ index = it->second;
+ printf("%5.2f\t\t%s (%i)\n", para->parameters[index], it->first.c_str(), index);
+ }
+
+ printf("\n");
+ printf("Score: %5.1f (%5.1f)\n", sqrt(para->score / (0.001 + past_results.size()) / average_power()), para->score);
+ printf("Guess: %5.1f\n", para->guessed_power);
+ printf("Actual: %5.1f\n", para->actual_power);
+
+ printf("----------------------------------\n");
+}
+
+void dump_result_bundle(struct result_bundle *res)
+{
+ map<string, int>::iterator it;
+ unsigned int index;
+
+ printf("\n\n");
+ printf("Utilisation state \n");
+ printf("----------------------------------\n");
+ printf("Value\t\tName\n");
+ for (it = result_index.begin(); it != result_index.end(); it++) {
+ index = get_result_index(it->first.c_str());
+ printf("%5.2f%%\t\t%s(%i)\n", res->utilization[index], it->first.c_str(), index);
+ }
+
+ printf("\n");
+ printf("Power: %5.1f\n", res->power);
+
+ printf("----------------------------------\n");
+}
+
+struct result_bundle * clone_results(struct result_bundle *bundle)
+{
+ struct result_bundle *b2;
+ map<string, double>::iterator it;
+ unsigned int i;
+
+ b2 = new struct result_bundle;
+
+ if (!b2)
+ return NULL;
+
+ b2->power = bundle->power;
+ b2->utilization.resize(bundle->utilization.size());
+
+ for (i = 0; i < bundle->utilization.size(); i++) {
+ b2->utilization[i] = bundle->utilization[i];
+ }
+
+ return b2;
+}
+
+
+struct parameter_bundle * clone_parameters(struct parameter_bundle *bundle)
+{
+ struct parameter_bundle *b2;
+ unsigned int i;
+
+ b2 = new struct parameter_bundle;
+
+ if (!b2)
+ return NULL;
+
+ b2->score = 0;
+ b2->guessed_power = 0;
+ b2->actual_power = bundle->actual_power;
+ b2->parameters.resize(bundle->parameters.size());
+ for (i = 0; i < bundle->parameters.size(); i++) {
+ b2->parameters[i] = bundle->parameters[i];
+ }
+
+ return b2;
+}
+
+
+void store_results(double duration)
+{
+ if (duration < 5)
+ return;
+ global_power();
+ if (all_results.power > 0.01) {
+ unsigned int overflow_index;
+ overflow_index = 50 + (rand() % MAX_KEEP);
+ if (past_results.size() >= MAX_PARAM) {
+ /* memory leak, must free old one first */
+ past_results[overflow_index] = clone_results(&all_results);
+ } else {
+ past_results.push_back(clone_results(&all_results));
+ }
+ if ((past_results.size() % 10) == 0)
+ save_all_results("saved_results.powertop");
+ }
+
+}
+
+
+
+void dump_past_results(void)
+{
+ unsigned int j;
+ unsigned int i;
+ struct result_bundle *result;
+
+ for (j = 0; j < past_results.size(); j+=10) {
+ printf("Est ");
+ for (i = j; i < past_results.size() && i < j + 10; i++) {
+ result = past_results[i];
+ printf("%6.2f ", bundle_power(&all_parameters, result));
+ }
+ printf("\n");
+ printf("Actual ");
+ for (i = j; i < past_results.size() && i < j + 10; i++) {
+ result = past_results[i];
+ printf("%6.2f ", result->power);
+ }
+ printf("\n\n");
+ }
+}
+
+double average_power(void)
+{
+ double sum = 0.0;
+ unsigned int i;
+ for (i = 0; i < past_results.size(); i++)
+ sum += past_results[i]->power;
+
+ if (past_results.size())
+ sum = sum / past_results.size() + 0.0001;
+ else
+ sum = 0.0001;
+ return sum;
+}
+
+int utilization_power_valid(const char *u)
+{
+ unsigned int i;
+ unsigned int index;
+ double first_value;
+
+ index = get_result_index(u);
+ if (index <= 0)
+ return 0;
+
+ first_value = past_results[0]->utilization[index];
+ for (i = 1; i < past_results.size(); i++) {
+ if (get_result_value(index, past_results[i]) < first_value - 0.0001)
+ return 1;
+ if (get_result_value(index, past_results[i]) > first_value + 0.0001)
+ return 1;
+ }
+
+ return 0;
+}
+
+int utilization_power_valid(int index)
+{
+ unsigned int i;
+ double first_value;
+
+ if (index <= 0)
+ return 0;
+
+ if (past_results.size() == 0)
+ return 0;
+
+ if (index >= (int)past_results[0]->utilization.size())
+ return 0;
+ first_value = past_results[0]->utilization[index];
+ for (i = 1; i < past_results.size(); i++) {
+ if (get_result_value(index, past_results[i]) < first_value - 0.0001)
+ return 1;
+ if (get_result_value(index, past_results[i]) > first_value + 0.0001)
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* force power data to be valid to the rest of the system */
+int global_power_override = 0;
+int global_run_times=0;
+/*
+ * only report power numbers once we have 3* more measurements than
+ * we have parameters; anything less and our model fit is highly suspect
+ */
+int global_power_valid(void)
+{
+ if (past_results.size() > 3 * all_parameters.parameters.size())
+ return 1;
+
+ if (past_results.size() > 0 && global_run_times < 1){
+ printf("To show power estimates do %ld measurement(s) connected to battery only\n",
+ (3 * all_parameters.parameters.size()) - past_results.size());
+ global_run_times += 1;
+ }
+
+ return global_power_override;
+}
+
+/* find the directory to store powertop results/parameters based on distribution*/
+char* get_param_directory(const char *filename)
+{
+ static char tempfilename[PATH_MAX];
+
+ if (access("/var/cache/powertop", W_OK ) == 0)
+ snprintf(tempfilename, sizeof(tempfilename), "/var/cache/powertop/%s", filename);
+ if (access("/data/local/powertop", W_OK ) == 0)
+ snprintf(tempfilename, sizeof(tempfilename), "/data/local/powertop/%s", filename);
+
+ return tempfilename;
+};
diff --git a/src/parameters/parameters.h b/src/parameters/parameters.h
new file mode 100644
index 0000000..1781a0e
--- /dev/null
+++ b/src/parameters/parameters.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef __INCLUDE_GUARD_PARAMETERS_H_
+#define __INCLUDE_GUARD_PARAMETERS_H_
+
+
+#include <map>
+#include <vector>
+#include <string>
+
+#include "string.h"
+#include "../devices/device.h"
+#include "../lib.h"
+
+using namespace std;
+
+#define MAX_KEEP 700
+#define MAX_PARAM 750
+
+
+struct parameter_bundle
+{
+ double score;
+ double guessed_power;
+ double actual_power;
+
+ vector<double> parameters;
+ vector<double> weights;
+};
+
+extern struct parameter_bundle all_parameters;
+extern map <string, int> param_index;
+extern map <string, int> result_index;
+
+extern int get_param_index(const char *param);
+extern int get_result_index(const char *param);
+
+
+extern void register_parameter(const char *name, double default_value = 0.00, double weight = 1.0);
+extern double get_parameter_value(const char *name, struct parameter_bundle *bundle = &all_parameters);
+extern double get_parameter_value(unsigned int index, struct parameter_bundle *bundle = &all_parameters);
+extern void set_parameter_value(const char *name, double value, struct parameter_bundle *bundle = &all_parameters);
+
+
+struct result_bundle
+{
+ double joules;
+ double power;
+ vector <double> utilization; /* device name, device utilization %age */
+};
+
+extern struct result_bundle all_results;
+extern vector <struct result_bundle *> past_results;
+
+extern double get_result_value(const char *name, struct result_bundle *bundle = &all_results);
+extern double get_result_value(int index, struct result_bundle *bundle = &all_results);
+
+extern void set_result_value(const char *name, double value, struct result_bundle *bundle = &all_results);
+
+
+extern int result_device_exists(const char *name);
+
+extern void report_utilization(const char *name, double value, struct result_bundle *bundle = &all_results);
+extern void report_utilization(int index, double value, struct result_bundle *bundle = &all_results);
+
+
+extern void precompute_valid(void);
+
+extern double compute_bundle(struct parameter_bundle *parameters = &all_parameters, struct result_bundle *results = &all_results);
+
+
+void dump_parameter_bundle(struct parameter_bundle *patameters = &all_parameters);
+void dump_result_bundle(struct result_bundle *res = &all_results);
+
+extern struct result_bundle * clone_results(struct result_bundle *bundle);
+extern struct parameter_bundle * clone_parameters(struct parameter_bundle *bundle);
+
+extern void store_results(double duration);
+extern void learn_parameters(int iterations, int do_base_power);
+extern char *get_param_directory(const char *filename);
+extern void save_all_results(const char *filename = "saved_results.powertop");
+extern void close_results(void);
+extern void load_results(const char *filename);
+extern void save_parameters(const char *filename);
+extern void load_parameters(const char *filename);
+
+extern void dump_past_results(void);
+extern double bundle_power(struct parameter_bundle *parameters, struct result_bundle *results);
+
+extern double average_power(void);
+
+extern int utilization_power_valid(const char *u);
+extern int utilization_power_valid(int index);
+extern double calculate_params(struct parameter_bundle *params = &all_parameters);
+int global_power_valid(void);
+
+
+extern int global_power_override;
+
+
+#endif
diff --git a/src/parameters/persistent.cpp b/src/parameters/persistent.cpp
new file mode 100644
index 0000000..0711b4d
--- /dev/null
+++ b/src/parameters/persistent.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <stdlib.h>
+
+#include "parameters.h"
+#include "../measurement/measurement.h"
+
+using namespace std;
+
+void save_all_results(const char *filename)
+{
+ ofstream file;
+ unsigned int i;
+ struct result_bundle *bundle;
+ char* pathname;
+
+ pathname = get_param_directory(filename);
+
+ file.open(pathname, ios::out);
+ if (!file) {
+ cout << _("Cannot save to file") << " " << pathname << "\n";
+ return;
+ }
+ for (i = 0; i < past_results.size(); i++) {
+ bundle = past_results[i];
+ map<string, int>::iterator it;
+ file << setiosflags(ios::fixed) << setprecision(5) << bundle->power << "\n";
+
+ for (it = result_index.begin(); it != result_index.end(); it++) {
+ file << it->first << "\t" << setprecision(5) << get_result_value(it->second, bundle) << "\n";
+ }
+ file << ":\n";
+ }
+
+ file.close();
+
+}
+
+void close_results()
+{
+ for (unsigned int i = 0; i < past_results.size(); i++) {
+ delete past_results[i];
+ }
+
+ past_results.clear();
+ return;
+}
+
+void load_results(const char *filename)
+{
+ ifstream file;
+ char line[4096];
+ char *c1;
+ struct result_bundle *bundle;
+ int first = 1;
+ unsigned int count = 0;
+ char* pathname;
+ int bundle_saved = 0;
+
+ pathname = get_param_directory(filename);
+
+ file.open(pathname, ios::in);
+ if (!file) {
+ cout << _("Cannot load from file") << " " << pathname << "\n";
+ return;
+ }
+
+ bundle = new struct result_bundle;
+
+ while (file) {
+ double d;
+ if (first) {
+ file.getline(line, 4096);
+ if (strlen(line)>0) {
+ sscanf(line, "%lf", &bundle->power);
+ if (bundle->power < min_power)
+ min_power = bundle->power;
+ }
+ first = 0;
+ continue;
+ }
+ file.getline(line, 4096);
+ if (strlen(line) < 3) {
+ int overflow_index;
+
+ bundle_saved = 1;
+ overflow_index = 50 + (rand() % MAX_KEEP);
+ if (past_results.size() >= MAX_PARAM) {
+ /* memory leak, must free old one first */
+ past_results[overflow_index] = bundle;
+ } else {
+ past_results.push_back(bundle);
+ }
+ bundle = new struct result_bundle;
+ first = 1;
+ count++;
+ continue;
+ }
+ c1 = strchr(line, '\t');
+ if (!c1)
+ continue;
+ *c1 = 0;
+ c1++;
+ sscanf(c1, "%lf", &d);
+ set_result_value(line, d, bundle);
+ }
+
+ if (bundle_saved == 0)
+ delete bundle;
+
+ file.close();
+ // '%i" is for count, do not translate
+ fprintf(stderr, _("Loaded %i prior measurements\n"), count);
+}
+
+void save_parameters(const char *filename)
+{
+ ofstream file;
+ char* pathname;
+
+// printf("result size is %i, #parameters is %i \n", (int)past_results.size(), (int)all_parameters.parameters.size());
+
+ if (!global_power_valid())
+ return;
+
+ pathname = get_param_directory(filename);
+
+ file.open(pathname, ios::out);
+ if (!file) {
+ cout << _("Cannot save to file") << " " << pathname << "\n";
+ return;
+ }
+
+ map<string, int>::iterator it;
+
+ for (it = param_index.begin(); it != param_index.end(); it++) {
+ int index;
+ index = it->second;
+ file << it->first << "\t" << setprecision(9) << all_parameters.parameters[index] << "\n";
+ }
+ file.close();
+}
+
+void load_parameters(const char *filename)
+{
+ ifstream file;
+ char line[4096];
+ char *c1;
+ char* pathname;
+
+ pathname = get_param_directory(filename);
+
+ file.open(pathname, ios::in);
+ if (!file) {
+ cout << _("Cannot load from file") << " " << pathname << "\n";
+ cout << _("File will be loaded after taking minimum number of measurement(s) with battery only \n");
+ return;
+ }
+
+ while (file) {
+ double d;
+ memset(line, 0, 4096);
+ file.getline(line, 4095);
+
+ c1 = strchr(line, '\t');
+ if (!c1)
+ continue;
+ *c1 = 0;
+ c1++;
+ sscanf(c1, "%lf", &d);
+
+
+ set_parameter_value(line, d);
+ }
+
+ file.close();
+}