[gnumeric] Add principal components analysis



commit 1032ae3f6351c5b4aa8e604541df8a50cd449e2b
Author: Andreas J. Guelzow <aguelzow pyrshep ca>
Date:   Tue Dec 22 16:33:24 2009 -0700

    Add principal components analysis
    
    2009-12-22  Andreas J. Guelzow <aguelzow pyrshep ca>
    
    	* POTFILES.in: added src/dialogs/dialog-analysis-tool-principal-components.c
    	  and src/tools/analysis-principal-components.c
    	* POTFILES.skip: added src/dialogs/principal-components.glade
    
    2009-12-22  Andreas J. Guelzow <aguelzow pyrshep ca>
    
    	* POTFILES.in: added src/dialogs/dialog-analysis--principal-components.c,
    	  src/tools/analysis-principal-components.c and
    	  src/dialogs/principal-components.glade
    
    2009-12-22  Andreas J. Guelzow <aguelzow pyrshep ca>
    
    	* component/Gnumeric-embed.xml.in: add principal components analysis
    	* src/HILDON_Gnumeric-gtk.xml.in: add principal components analysis
    	* src/GNOME_Gnumeric-gtk.xml.in: add principal components analysis
    	* src/wbc-gtk-actions.c: add principal components analysis action
    	* src/mathfunc.c (gnm_matrix_eigen): handle 1 by 1 matrix.
    
    2009-12-22 Andreas J. Guelzow <aguelzow pyrshep ca>
    
    	* dialog-analysis-tool-principal-components.c: new
    	* principal-components.glade: new
    	* Makefile.am: add the above
    	* dialogs.h (dialog_principal_components_tool): new
    	* help.h (GNUMERIC_HELP_LINK_PRINCIPAL_COMPONENTS): new
    
    2009-12-22 Andreas J. Guelzow <aguelzow pyrshep ca>
    
    	* analysis-principal-components.c: new
    	* analysis-principal-components.h: new
    	* Makefile.am: add the above
    	* analysis-tools.c (analysis_tool_table): make non-static and add
    	  full_table argument. Change all callers.
    	* analysis-tools.h (analysis_tool_table): new

 ChangeLog                                          |    8 +
 NEWS                                               |    1 +
 component/Gnumeric-embed.xml.in                    |    1 +
 po-functions/ChangeLog                             |    6 +
 po-functions/POTFILES.in                           |    2 +
 po-functions/POTFILES.skip                         |    1 +
 po/ChangeLog                                       |    6 +
 po/POTFILES.in                                     |    3 +
 src/GNOME_Gnumeric-gtk.xml.in                      |    1 +
 src/HILDON_Gnumeric-gtk.xml.in                     |    1 +
 src/dialogs/ChangeLog                              |    8 +
 src/dialogs/Makefile.am                            |    6 +-
 .../dialog-analysis-tool-principal-components.c    |  186 +++++++++++
 src/dialogs/dialogs.h                              |    1 +
 src/dialogs/help.h                                 |    1 +
 src/dialogs/principal-components.glade             |  323 ++++++++++++++++++++
 src/mathfunc.c                                     |    2 +-
 src/tools/ChangeLog                                |    9 +
 src/tools/Makefile.am                              |    2 +
 src/tools/analysis-principal-components.c          |  240 +++++++++++++++
 src/tools/analysis-principal-components.h          |   41 +++
 src/tools/analysis-tools.c                         |   15 +-
 src/tools/analysis-tools.h                         |    5 +
 src/wbc-gtk-actions.c                              |    5 +
 24 files changed, 865 insertions(+), 9 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index bbd0bbc..955b20d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2009-12-22  Andreas J. Guelzow <aguelzow pyrshep ca>
+
+	* component/Gnumeric-embed.xml.in: add principal components analysis
+	* src/HILDON_Gnumeric-gtk.xml.in: add principal components analysis
+	* src/GNOME_Gnumeric-gtk.xml.in: add principal components analysis
+	* src/wbc-gtk-actions.c: add principal components analysis action
+	* src/mathfunc.c (gnm_matrix_eigen): handle 1 by 1 matrix.
+
 2009-12-21  Andreas J. Guelzow <aguelzow pyrshep ca>
 
 	* src/mathfunc.h (gnm_matrix_eigen): new
diff --git a/NEWS b/NEWS
index c9c5ba3..ce63b7a 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,7 @@ Andreas:
 	* Add paste special flip horizontally and vertically [#393367]
 	* Add EIGEN function to calculate eigenvalues and eigenvectors
 	  of real symmetric matrices
+	* Add principal components analysis
 
 Jean
 	* Fix import export of line type in scatter plots. [#605043]
diff --git a/component/Gnumeric-embed.xml.in b/component/Gnumeric-embed.xml.in
index 2693d15..f120233 100644
--- a/component/Gnumeric-embed.xml.in
+++ b/component/Gnumeric-embed.xml.in
@@ -184,6 +184,7 @@
         </menu>
         <menuitem action="ToolsKaplanMeier"/>
         <menuitem action="ToolsNormalityTests"/>
+        <menuitem action="ToolsPrincipalComponents"/>
         <menuitem action="ToolsRanking"/>
         <menuitem action="ToolsRegression"/>
         <menuitem action="ToolsSampling"/>
diff --git a/po-functions/ChangeLog b/po-functions/ChangeLog
index 3064dff..b35ccbf 100644
--- a/po-functions/ChangeLog
+++ b/po-functions/ChangeLog
@@ -1,3 +1,9 @@
+2009-12-22  Andreas J. Guelzow <aguelzow pyrshep ca>
+
+	* POTFILES.in: added src/dialogs/dialog-analysis-tool-principal-components.c
+	  and src/tools/analysis-principal-components.c
+	* POTFILES.skip: added src/dialogs/principal-components.glade
+
 2009-12-17  Andreas J. Guelzow <aguelzow pyrshep ca>
 
 	* POTFILES.skip: added src/dialogs/paste-special.glade
diff --git a/po-functions/POTFILES.in b/po-functions/POTFILES.in
index a9b7463..3136c16 100644
--- a/po-functions/POTFILES.in
+++ b/po-functions/POTFILES.in
@@ -77,6 +77,7 @@ src/dialogs/dialog-analysis-tool-chi-squared.c
 src/dialogs/dialog-analysis-tool-frequency.c
 src/dialogs/dialog-analysis-tool-kaplan-meier.c
 src/dialogs/dialog-analysis-tool-normality.c
+src/dialogs/dialog-analysis-tool-principal-components.c
 src/dialogs/dialog-analysis-tool-sign-test.c
 src/dialogs/dialog-analysis-tools.c
 src/dialogs/dialog-autofilter.c
@@ -197,6 +198,7 @@ src/tools/analysis-frequency.c
 src/tools/analysis-histogram.c
 src/tools/analysis-kaplan-meier.c
 src/tools/analysis-normality.c
+src/tools/analysis-principal-components.c
 src/tools/analysis-sign-test.c
 src/tools/analysis-tools.c
 src/tools/dao.c
diff --git a/po-functions/POTFILES.skip b/po-functions/POTFILES.skip
index dc2bfd2..9e1a422 100644
--- a/po-functions/POTFILES.skip
+++ b/po-functions/POTFILES.skip
@@ -116,6 +116,7 @@ src/dialogs/paste-special.glade
 src/dialogs/plugin-manager.glade
 src/dialogs/preferences.glade
 src/dialogs/print.glade
+src/dialogs/principal-components.glade
 src/dialogs/random-generation.glade
 src/dialogs/random-generation-cor.glade
 src/dialogs/rank.glade
diff --git a/po/ChangeLog b/po/ChangeLog
index 0bc5c23..5bb4e59 100644
--- a/po/ChangeLog
+++ b/po/ChangeLog
@@ -1,3 +1,9 @@
+2009-12-22  Andreas J. Guelzow <aguelzow pyrshep ca>
+
+	* POTFILES.in: added src/dialogs/dialog-analysis--principal-components.c,
+	  src/tools/analysis-principal-components.c and 
+	  src/dialogs/principal-components.glade
+
 2009-12-17  Andreas J. Guelzow <aguelzow pyrshep ca>
 
 	* POTFILES.in: added src/dialogs/paste-special.glade
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f5c8b57..4cb2b61 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -157,6 +157,7 @@ src/dialogs/dialog-analysis-tool-chi-squared.c
 src/dialogs/dialog-analysis-tool-frequency.c
 src/dialogs/dialog-analysis-tool-kaplan-meier.c
 src/dialogs/dialog-analysis-tool-normality.c
+src/dialogs/dialog-analysis-tool-principal-components.c
 src/dialogs/dialog-analysis-tool-sign-test.c
 src/dialogs/dialog-analysis-tools.c
 src/dialogs/dialog-autofilter.c
@@ -240,6 +241,7 @@ src/dialogs/paste-special.glade
 src/dialogs/plugin-manager.glade
 src/dialogs/preferences.glade
 src/dialogs/print.glade
+src/dialogs/principal-components.glade
 src/dialogs/random-generation.glade
 src/dialogs/random-generation-cor.glade
 src/dialogs/rank.glade
@@ -331,6 +333,7 @@ src/tools/analysis-frequency.c
 src/tools/analysis-histogram.c
 src/tools/analysis-kaplan-meier.c
 src/tools/analysis-normality.c
+src/tools/analysis-principal-components.c
 src/tools/analysis-sign-test.c
 src/tools/analysis-tools.c
 src/tools/dao.c
diff --git a/src/GNOME_Gnumeric-gtk.xml.in b/src/GNOME_Gnumeric-gtk.xml.in
index 3db4f1a..c4c10a9 100644
--- a/src/GNOME_Gnumeric-gtk.xml.in
+++ b/src/GNOME_Gnumeric-gtk.xml.in
@@ -183,6 +183,7 @@
         </menu>
         <menuitem action="ToolsKaplanMeier"/>
         <menuitem action="ToolsNormalityTests"/>
+        <menuitem action="ToolsPrincipalComponents"/>
         <menuitem action="ToolsRanking"/>
         <menuitem action="ToolsRegression"/>
         <menuitem action="ToolsSampling"/>
diff --git a/src/HILDON_Gnumeric-gtk.xml.in b/src/HILDON_Gnumeric-gtk.xml.in
index a9752b7..3f816e1 100644
--- a/src/HILDON_Gnumeric-gtk.xml.in
+++ b/src/HILDON_Gnumeric-gtk.xml.in
@@ -189,6 +189,7 @@
 	</menu>
         <menuitem action="ToolsKaplanMeier"/>
         <menuitem action="ToolsNormalityTests"/>
+        <menuitem action="ToolsPrincipalComponents"/>
         <menuitem action="ToolsRanking"/>
         <menuitem action="ToolsRegression"/>
         <menuitem action="ToolsSampling"/>
diff --git a/src/dialogs/ChangeLog b/src/dialogs/ChangeLog
index 74e19bb..07dd2fa 100644
--- a/src/dialogs/ChangeLog
+++ b/src/dialogs/ChangeLog
@@ -1,3 +1,11 @@
+2009-12-22 Andreas J. Guelzow <aguelzow pyrshep ca>
+
+	* dialog-analysis-tool-principal-components.c: new
+	* principal-components.glade: new
+	* Makefile.am: add the above
+	* dialogs.h (dialog_principal_components_tool): new
+	* help.h (GNUMERIC_HELP_LINK_PRINCIPAL_COMPONENTS): new
+
 2009-12-19  Andreas J. Guelzow <aguelzow pyrshep ca>
 
 	* paste-special.glade: eanble flip h and v
diff --git a/src/dialogs/Makefile.am b/src/dialogs/Makefile.am
index 7f24ecc..77d6917 100644
--- a/src/dialogs/Makefile.am
+++ b/src/dialogs/Makefile.am
@@ -30,6 +30,7 @@ base_files =					\
 	dialog-analysis-tool-frequency.c	\
 	dialog-analysis-tool-kaplan-meier.c	\
 	dialog-analysis-tool-normality.c	\
+	dialog-analysis-tool-principal-components.c	\
 	dialog-analysis-tool-sign-test.c	\
 	dialog-autofilter.c			\
 	dialog-autoformat.c			\
@@ -137,12 +138,11 @@ glade_DATA = 				\
 	merge.glade			\
 	moving-averages.glade		\
 	normality-tests.glade		\
-	sign-test.glade			\
-	sign-test-two.glade		\
 	paste-names.glade		\
 	paste-special.glade		\
 	plugin-manager.glade		\
 	preferences.glade 		\
+	principal-components.glade	\
 	rank.glade			\
 	random-generation.glade		\
 	random-generation-cor.glade	\
@@ -155,6 +155,8 @@ glade_DATA = 				\
 	sheet-order.glade		\
 	sheet-resize.glade              \
 	shuffle.glade			\
+	sign-test.glade			\
+	sign-test-two.glade		\
 	so-button.glade			\
  	so-radiobutton.glade		\
 	so-checkbox.glade		\
diff --git a/src/dialogs/dialog-analysis-tool-principal-components.c b/src/dialogs/dialog-analysis-tool-principal-components.c
new file mode 100644
index 0000000..c53273c
--- /dev/null
+++ b/src/dialogs/dialog-analysis-tool-principal-components.c
@@ -0,0 +1,186 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * dialog-analysis-tool-principal-components.c:
+ *
+ * Authors:
+  *  Andreas J. Guelzow  <aguelzow taliesin ca>
+ *
+ * (C) Copyright 2009 by Andreas J. Guelzow  <aguelzow pyrshep ca>
+ *
+ * This program 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <gnumeric-config.h>
+#include <glib/gi18n-lib.h>
+#include <gnumeric.h>
+#include "dialogs.h"
+#include "analysis-principal-components.h"
+#include "analysis-tools.h"
+
+#include <workbook.h>
+#include <workbook-control.h>
+#include <wbc-gtk.h>
+#include <workbook-view.h>
+#include <gui-util.h>
+#include <parse-util.h>
+#include <gnm-format.h>
+#include <tool-dialogs.h>
+#include <dao-gui-utils.h>
+#include <sheet.h>
+#include <expr.h>
+#include <number-match.h>
+#include <ranges.h>
+#include <selection.h>
+#include <value.h>
+#include <commands.h>
+#include "help.h"
+
+#include <widgets/gnm-dao.h>
+#include <widgets/gnumeric-expr-entry.h>
+
+#include <glade/glade.h>
+#include <string.h>
+#include <gtk/gtk.h>
+
+#define PRINCIPAL_COMPONENTS_KEY "analysistools-principal-components-dialog"
+
+static char const * const grouped_by_group[] = {
+	"grouped_by_row",
+	"grouped_by_col",
+	"grouped_by_area",
+	NULL
+};
+
+static void
+principal_components_tool_update_sensitivity_cb (G_GNUC_UNUSED GtkWidget *dummy,
+						 GenericToolState *state)
+{
+        GSList *input_range;
+
+	/* Checking Input Range */
+        input_range = gnm_expr_entry_parse_as_list (
+		GNM_EXPR_ENTRY (state->input_entry), state->sheet);
+	if (input_range == NULL) {
+		gtk_label_set_text (GTK_LABEL (state->warning),
+				    _("The input range is invalid."));
+		gtk_widget_set_sensitive (state->ok_button, FALSE);
+		return;
+	} else
+		range_list_destroy (input_range);
+
+	/* Checking Output Page */
+	if (!gnm_dao_is_ready (GNM_DAO (state->gdao))) {
+		gtk_label_set_text (GTK_LABEL (state->warning),
+				    _("The output specification "
+				      "is invalid."));
+		gtk_widget_set_sensitive (state->ok_button, FALSE);
+		return;
+	}
+
+	gtk_label_set_text (GTK_LABEL (state->warning), "");
+	gtk_widget_set_sensitive (state->ok_button, TRUE);
+
+	return;
+}
+
+/**
+ * principal_components_tool_ok_clicked_cb:
+ * @button:
+ * @state:
+ *
+ **/
+static void
+principal_components_tool_ok_clicked_cb (G_GNUC_UNUSED GtkWidget *button,
+			GenericToolState *state)
+{
+	data_analysis_output_t  *dao;
+	analysis_tools_data_generic_t  *data;
+
+        char   *text;
+	GtkWidget *w;
+
+	if (state->warning_dialog != NULL)
+		gtk_widget_destroy (state->warning_dialog);
+
+	data = g_new0 (analysis_tools_data_generic_t, 1);
+	dao  = parse_output (state, NULL);
+
+	data->input = gnm_expr_entry_parse_as_list (
+		GNM_EXPR_ENTRY (state->input_entry), state->sheet);
+	data->group_by = gnumeric_glade_group_value (state->gui, grouped_by_group);
+
+	w = glade_xml_get_widget (state->gui, "labels_button");
+        data->labels = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
+
+	if (cmd_analysis_tool (WORKBOOK_CONTROL (state->wbcg), state->sheet,
+			       dao, data, analysis_tool_principal_components_engine)) {
+		text = g_strdup_printf (
+			_("An unexpected error has occurred: %d."), data->err);
+		error_in_entry ((GenericToolState *) state,
+				GTK_WIDGET (state->input_entry), text);
+		g_free (text);
+		range_list_destroy (data->input);
+		g_free (dao);
+		g_free (data);
+	} else
+		gtk_widget_destroy (state->dialog);
+	return;
+}
+
+
+
+/**
+ * dialog_principal_components_tool:
+ * @wbcg:
+ * @sheet:
+ *
+ * Show the dialog (guru).
+ *
+ **/
+int
+dialog_principal_components_tool (WBCGtk *wbcg, Sheet *sheet)
+{
+        GenericToolState *state;
+	char const * plugins[] = { "Gnumeric_fnstat", 
+				   "Gnumeric_fnmath",
+				   "Gnumeric_fnlogical",
+				   NULL};
+
+	if ((wbcg == NULL) ||
+	    gnm_check_for_plugins_missing (plugins, wbcg_toplevel (wbcg)))
+		return 1;
+
+	/* Only pop up one copy per workbook */
+	if (gnumeric_dialog_raise_if_exists (wbcg, PRINCIPAL_COMPONENTS_KEY))
+		return 0;
+
+	state = g_new0 (GenericToolState, 1);
+
+	if (dialog_tool_init (state, wbcg, sheet,
+			      GNUMERIC_HELP_LINK_PRINCIPAL_COMPONENTS,
+			      "principal-components.glade", "PrincipalComponents",
+			      _("Could not create the Principal Components Analysis Tool dialog."),
+			      PRINCIPAL_COMPONENTS_KEY,
+			      G_CALLBACK (principal_components_tool_ok_clicked_cb), NULL,
+			      G_CALLBACK (principal_components_tool_update_sensitivity_cb),
+			      GNM_EE_SINGLE_RANGE))
+		return 0;
+
+	gnm_dao_set_put (GNM_DAO (state->gdao), TRUE, TRUE);
+	principal_components_tool_update_sensitivity_cb (NULL, state);
+	tool_load_selection ((GenericToolState *)state, TRUE);
+
+        return 0;
+}
diff --git a/src/dialogs/dialogs.h b/src/dialogs/dialogs.h
index 5c2fe22..e062084 100644
--- a/src/dialogs/dialogs.h
+++ b/src/dialogs/dialogs.h
@@ -93,6 +93,7 @@ int dialog_frequency_tool	 (WBCGtk *wbcg, Sheet *sheet);
 int dialog_kaplan_meier_tool	 (WBCGtk *wbcg, Sheet *sheet);
 int dialog_normality_tool	 (WBCGtk *wbcg, Sheet *sheet);
 int dialog_chi_square_tool       (WBCGtk *wbcg, Sheet *sheet, gboolean independence);
+int dialog_principal_components_tool	 (WBCGtk *wbcg, Sheet *sheet);
 
 typedef enum {
 	SIGNTEST_1 = 1,
diff --git a/src/dialogs/help.h b/src/dialogs/help.h
index 949f929..4fbf659 100644
--- a/src/dialogs/help.h
+++ b/src/dialogs/help.h
@@ -145,6 +145,7 @@
 #define GNUMERIC_HELP_LINK_HISTOGRAM "sect-analysis-statistical"
 #define GNUMERIC_HELP_LINK_ANOVA_SINGLE_FACTOR "sect-analysis-statistical"
 #define GNUMERIC_HELP_LINK_ANOVA_TWO_FACTOR "sect-analysis-statistical"
+#define GNUMERIC_HELP_LINK_PRINCIPAL_COMPONENTS "sect-analysis-statistical"
 
 /* dialog-analysis-tool-chi-squared.c */
 #define GNUMERIC_HELP_LINK_CHI_SQUARED "sect-analysis-statistical"
diff --git a/src/dialogs/principal-components.glade b/src/dialogs/principal-components.glade
new file mode 100644
index 0000000..e384086
--- /dev/null
+++ b/src/dialogs/principal-components.glade
@@ -0,0 +1,323 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd";>
+
+<glade-interface>
+
+<widget class="GtkDialog" id="PrincipalComponents">
+  <property name="title" translatable="yes">Principal Components Analysis</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="has_separator">False</property>
+
+  <child internal-child="vbox">
+    <widget class="GtkVBox" id="vbox1">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">8</property>
+
+      <child internal-child="action_area">
+	<widget class="GtkHButtonBox" id="hbuttonbox1">
+	  <property name="visible">True</property>
+	  <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+	  <child>
+	    <widget class="GtkButton" id="helpbutton">
+	      <property name="visible">True</property>
+	      <property name="can_default">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="label">gtk-help</property>
+	      <property name="use_stock">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="response_id">0</property>
+	    </widget>
+	  </child>
+
+	  <child>
+	    <widget class="GtkButton" id="cancelbutton">
+	      <property name="visible">True</property>
+	      <property name="can_default">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="label">gtk-cancel</property>
+	      <property name="use_stock">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="response_id">0</property>
+	    </widget>
+	  </child>
+
+	  <child>
+	    <widget class="GtkButton" id="okbutton">
+	      <property name="visible">True</property>
+	      <property name="can_default">True</property>
+	      <property name="has_default">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="label">gtk-ok</property>
+	      <property name="use_stock">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="response_id">0</property>
+	    </widget>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">True</property>
+	  <property name="pack_type">GTK_PACK_END</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkNotebook" id="notebook1">
+	  <property name="visible">True</property>
+	  <property name="can_focus">True</property>
+	  <property name="show_tabs">True</property>
+	  <property name="show_border">True</property>
+	  <property name="tab_pos">GTK_POS_TOP</property>
+	  <property name="scrollable">False</property>
+	  <property name="enable_popup">False</property>
+
+	  <child>
+	    <widget class="GtkTable" id="input-table">
+	      <property name="border_width">12</property>
+	      <property name="visible">True</property>
+	      <property name="n_rows">3</property>
+	      <property name="n_columns">2</property>
+	      <property name="homogeneous">False</property>
+	      <property name="row_spacing">6</property>
+	      <property name="column_spacing">12</property>
+
+	      <child>
+		<widget class="GtkLabel" id="var1-label">
+		  <property name="visible">True</property>
+		  <property name="label" translatable="yes">_Input range:</property>
+		  <property name="use_underline">True</property>
+		  <property name="use_markup">False</property>
+		  <property name="justify">GTK_JUSTIFY_RIGHT</property>
+		  <property name="wrap">False</property>
+		  <property name="selectable">False</property>
+		  <property name="xalign">0</property>
+		  <property name="yalign">0.5</property>
+		  <property name="xpad">5</property>
+		  <property name="ypad">0</property>
+		</widget>
+		<packing>
+		  <property name="left_attach">0</property>
+		  <property name="right_attach">1</property>
+		  <property name="top_attach">0</property>
+		  <property name="bottom_attach">1</property>
+		  <property name="x_options">fill</property>
+		  <property name="y_options"></property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkLabel" id="label2">
+		  <property name="visible">True</property>
+		  <property name="label" translatable="yes">Grouped by:</property>
+		  <property name="use_underline">False</property>
+		  <property name="use_markup">False</property>
+		  <property name="justify">GTK_JUSTIFY_CENTER</property>
+		  <property name="wrap">False</property>
+		  <property name="selectable">False</property>
+		  <property name="xalign">0</property>
+		  <property name="yalign">0.5</property>
+		  <property name="xpad">5</property>
+		  <property name="ypad">0</property>
+		</widget>
+		<packing>
+		  <property name="left_attach">0</property>
+		  <property name="right_attach">1</property>
+		  <property name="top_attach">1</property>
+		  <property name="bottom_attach">2</property>
+		  <property name="x_options">fill</property>
+		  <property name="y_options"></property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkCheckButton" id="labels_button">
+		  <property name="visible">True</property>
+		  <property name="can_focus">True</property>
+		  <property name="label" translatable="yes">_Labels</property>
+		  <property name="use_underline">True</property>
+		  <property name="relief">GTK_RELIEF_NORMAL</property>
+		  <property name="active">False</property>
+		  <property name="inconsistent">False</property>
+		  <property name="draw_indicator">True</property>
+		</widget>
+		<packing>
+		  <property name="left_attach">0</property>
+		  <property name="right_attach">1</property>
+		  <property name="top_attach">2</property>
+		  <property name="bottom_attach">3</property>
+		  <property name="x_options">fill</property>
+		  <property name="y_options"></property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkHBox" id="vbox2">
+		  <property name="visible">True</property>
+		  <property name="homogeneous">True</property>
+		  <property name="spacing">0</property>
+
+		  <child>
+		    <widget class="GtkRadioButton" id="grouped_by_col">
+		      <property name="visible">True</property>
+		      <property name="can_focus">True</property>
+		      <property name="label" translatable="yes">_Columns</property>
+		      <property name="use_underline">True</property>
+		      <property name="relief">GTK_RELIEF_NORMAL</property>
+		      <property name="active">True</property>
+		      <property name="inconsistent">False</property>
+		      <property name="draw_indicator">True</property>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">False</property>
+		      <property name="fill">False</property>
+		    </packing>
+		  </child>
+
+		  <child>
+		    <widget class="GtkRadioButton" id="grouped_by_row">
+		      <property name="visible">True</property>
+		      <property name="can_focus">True</property>
+		      <property name="label" translatable="yes">_Rows</property>
+		      <property name="use_underline">True</property>
+		      <property name="relief">GTK_RELIEF_NORMAL</property>
+		      <property name="active">False</property>
+		      <property name="inconsistent">False</property>
+		      <property name="draw_indicator">True</property>
+		      <property name="group">grouped_by_col</property>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">False</property>
+		      <property name="fill">False</property>
+		    </packing>
+		  </child>
+
+		  <child>
+		    <widget class="GtkRadioButton" id="grouped_by_area">
+		      <property name="visible">False</property>
+		      <property name="sensitive">False</property>
+		      <property name="can_focus">True</property>
+		      <property name="label" translatable="yes">_Areas</property>
+		      <property name="use_underline">True</property>
+		      <property name="relief">GTK_RELIEF_NORMAL</property>
+		      <property name="active">False</property>
+		      <property name="inconsistent">False</property>
+		      <property name="draw_indicator">True</property>
+		      <property name="group">grouped_by_col</property>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">False</property>
+		      <property name="fill">False</property>
+		    </packing>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="left_attach">1</property>
+		  <property name="right_attach">2</property>
+		  <property name="top_attach">1</property>
+		  <property name="bottom_attach">2</property>
+		  <property name="y_options">fill</property>
+		</packing>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="tab_expand">False</property>
+	      <property name="tab_fill">True</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="label4">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">Input</property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_LEFT</property>
+	      <property name="wrap">False</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0.5</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	    </widget>
+	    <packing>
+	      <property name="type">tab</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkHBox" id="dao">
+	      <property name="visible">True</property>
+	      <property name="homogeneous">False</property>
+	      <property name="spacing">0</property>
+
+	      <child>
+		<placeholder/>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="tab_expand">False</property>
+	      <property name="tab_fill">True</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="label5">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">Output</property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_LEFT</property>
+	      <property name="wrap">False</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0.5</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	    </widget>
+	    <packing>
+	      <property name="type">tab</property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkLabel" id="warnings">
+	  <property name="visible">True</property>
+	  <property name="label" translatable="yes"></property>
+	  <property name="use_underline">False</property>
+	  <property name="use_markup">False</property>
+	  <property name="justify">GTK_JUSTIFY_LEFT</property>
+	  <property name="wrap">True</property>
+	  <property name="selectable">False</property>
+	  <property name="xalign">0.5</property>
+	  <property name="yalign">0.5</property>
+	  <property name="xpad">0</property>
+	  <property name="ypad">0</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+</glade-interface>
diff --git a/src/mathfunc.c b/src/mathfunc.c
index 086961d..5443e8b 100644
--- a/src/mathfunc.c
+++ b/src/mathfunc.c
@@ -7856,7 +7856,7 @@ gnm_matrix_eigen (gnm_float **matrix, gnm_float **eigenvectors, gnm_float *eigen
 		changed[i] = TRUE;
 	}
 
-	while (state != 0) {
+	while (size > 1 && state != 0) {
 		int k, l, m = 0;
 		gnm_float c, s, y, pivot, t;
 		
diff --git a/src/tools/ChangeLog b/src/tools/ChangeLog
index dab604c..789d3ee 100644
--- a/src/tools/ChangeLog
+++ b/src/tools/ChangeLog
@@ -1,3 +1,12 @@
+2009-12-22 Andreas J. Guelzow <aguelzow pyrshep ca>
+
+	* analysis-principal-components.c: new
+	* analysis-principal-components.h: new
+	* Makefile.am: add the above
+	* analysis-tools.c (analysis_tool_table): make non-static and add 
+	  full_table argument. Change all callers.
+	* analysis-tools.h (analysis_tool_table): new
+
 2009-12-15  Morten Welinder <terra gnome org>
 
 	* Release 1.9.17
diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am
index 0d42936..da4dcc8 100644
--- a/src/tools/Makefile.am
+++ b/src/tools/Makefile.am
@@ -29,6 +29,8 @@ libtools_la_SOURCES =					\
 	analysis-kaplan-meier.h				\
 	analysis-normality.c				\
 	analysis-normality.h				\
+	analysis-principal-components.c			\
+	analysis-principal-components.h			\
 	analysis-sign-test.c				\
 	analysis-sign-test.h				\
 	analysis-tools.c				\
diff --git a/src/tools/analysis-principal-components.c b/src/tools/analysis-principal-components.c
new file mode 100644
index 0000000..6669060
--- /dev/null
+++ b/src/tools/analysis-principal-components.c
@@ -0,0 +1,240 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * analysis-principal-components.c:
+ *
+ * Author:
+ *   Andreas J. Guelzow  <aguelzow pyrshep ca>
+ *
+ * (C) Copyright 2009 by Andreas J. Guelzow  <aguelzow pyrshep ca>
+ *
+ *
+ * This program 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <gnumeric-config.h>
+#include <glib/gi18n-lib.h>
+#include "gnumeric.h"
+#include "analysis-principal-components.h"
+#include "analysis-tools.h"
+#include "value.h"
+#include "ranges.h"
+#include "expr.h"
+#include "func.h"
+#include "numbers.h"
+
+static gboolean
+analysis_tool_principal_components_engine_run (data_analysis_output_t *dao,
+				      analysis_tools_data_generic_t *info)
+{
+	int l = g_slist_length (info->input), i;
+	GSList *inputdata;
+
+	GnmFunc *fd_mean;
+	GnmFunc *fd_var;
+	GnmFunc *fd_eigen;
+	GnmFunc *fd_mmult;
+	GnmFunc *fd_munit;
+	GnmFunc *fd_sqrt;
+	GnmFunc *fd_count;
+	GnmFunc *fd_sum;
+	GnmFunc *fd_and;
+	GnmFunc *fd_if;
+
+	GnmExpr const *expr;
+	GnmExpr const *expr_count;
+	GnmExpr const *expr_munit;
+	GnmExpr const *expr_and;
+	
+	int data_points;
+	GnmExprList *and_args = NULL;
+
+	if (!dao_cell_is_visible (dao, l, 9 + 3 * l)) {
+		dao_set_bold (dao, 0, 0, 0, 0);
+		dao_set_italic (dao, 0, 0, 0, 0);
+		dao_set_cell (dao, 0, 0, 
+			      _("Principal components analysis has "
+				"insufficient space."));
+		return 0;
+	}
+
+	fd_mean = gnm_func_lookup_or_add_placeholder 
+		("AVERAGE", dao->sheet ? dao->sheet->workbook : NULL, FALSE);
+	gnm_func_ref (fd_mean);
+	fd_var = gnm_func_lookup_or_add_placeholder 
+		("VAR", dao->sheet ? dao->sheet->workbook : NULL, FALSE);
+	gnm_func_ref (fd_var);
+	fd_eigen = gnm_func_lookup_or_add_placeholder 
+		("EIGEN", dao->sheet ? dao->sheet->workbook : NULL, FALSE);
+	gnm_func_ref (fd_eigen);
+	fd_mmult = gnm_func_lookup_or_add_placeholder 
+		("MMULT", dao->sheet ? dao->sheet->workbook : NULL, FALSE);
+	gnm_func_ref (fd_mmult);
+	fd_munit = gnm_func_lookup_or_add_placeholder 
+		("MUNIT", dao->sheet ? dao->sheet->workbook : NULL, FALSE);
+	gnm_func_ref (fd_munit);
+	fd_sqrt = gnm_func_lookup_or_add_placeholder 
+		("SQRT", dao->sheet ? dao->sheet->workbook : NULL, FALSE);
+	gnm_func_ref (fd_sqrt);
+	fd_count = gnm_func_lookup_or_add_placeholder 
+		("COUNT", dao->sheet ? dao->sheet->workbook : NULL, FALSE);
+	gnm_func_ref (fd_count);
+	fd_sum = gnm_func_lookup_or_add_placeholder 
+		("SUM", dao->sheet ? dao->sheet->workbook : NULL, FALSE);
+	gnm_func_ref (fd_sum);
+	fd_and = gnm_func_lookup_or_add_placeholder 
+		("AND", dao->sheet ? dao->sheet->workbook : NULL, FALSE);
+	gnm_func_ref (fd_and);
+	fd_if = gnm_func_lookup_or_add_placeholder 
+		("IF", dao->sheet ? dao->sheet->workbook : NULL, FALSE);
+	gnm_func_ref (fd_if);
+
+	dao_set_bold (dao, 0, 0, 0, 0);
+	dao_set_italic (dao, 0, 0, 0, 11 + 3 * l);
+	dao_set_format (dao, 0, 0, 0, 0, 
+			_("\"Principal Components Analysis\";"
+			  "[Red]\"Principal Components Analysis is invalid.\""));
+	dao_set_align (dao, 0, 0, 0, 0,
+		       HALIGN_LEFT, VALIGN_BOTTOM);
+
+	dao->offset_row++;
+	analysis_tool_table (dao, info, _("Covariances:"), "COVAR", TRUE);
+	dao->offset_row--;
+
+	for (i = 1, inputdata = info->input; inputdata != NULL; i++, inputdata = inputdata->next)
+		analysis_tools_write_label (inputdata->data, dao, info, 0, 9 + 2 * l + i, i);
+
+	data_points = value_area_get_width (info->input->data, NULL) * 
+		value_area_get_height (info->input->data, NULL);
+	for (i = 0; i < l; i++)
+		and_args = gnm_expr_list_prepend 
+			(and_args, 
+			 gnm_expr_new_binary 
+			 (gnm_expr_new_constant (value_new_int (data_points)),
+			  GNM_EXPR_OP_EQUAL,
+			  make_cellref (1 + i, 3 + l)));
+	expr_and = gnm_expr_new_funcall	(fd_and, and_args);
+	dao_set_cell_expr (dao, 0, 0, 
+			   gnm_expr_new_funcall3 
+			   (fd_if,
+			    expr_and,
+			    gnm_expr_new_constant (value_new_int (1)),
+			    gnm_expr_new_constant (value_new_int (-1))));
+	dao_set_merge (dao,0,0,2,0);
+	set_cell_text_col (dao, 0, 3 + l, 
+			   _("/Count:"
+			     "/Mean:"
+			     "/Variance:"
+			     "//Eigenvalues:"
+			     "/Eigenvectors:"));
+	dao_set_cell (dao, 0, 11 + 3 * l, _("Percent of Trace:"));
+	dao_set_italic (dao, 0, 9 + 2 * l, 1 + l, 9 + 2 * l);
+	dao_set_percent (dao, 1, 11 + 3 * l, 1 + l, 11 + 3 * l);
+
+	for (i = 1, inputdata = info->input; inputdata != NULL; i++, inputdata = inputdata->next) {
+		expr = gnm_expr_new_constant (value_dup (inputdata->data));
+		
+		dao_set_cell_expr (dao, i, 3 + l, 
+				   gnm_expr_new_funcall1 (fd_count, gnm_expr_copy (expr)));
+		dao_set_cell_expr (dao, i, 4 + l,  
+				   gnm_expr_new_funcall1 (fd_mean, gnm_expr_copy (expr)));
+		dao_set_cell_expr (dao, i, 5 + l,
+				   gnm_expr_new_funcall1 (fd_var, expr));
+	}
+
+	expr_count = gnm_expr_new_binary (make_cellref (0,-4), GNM_EXPR_OP_DIV,
+					  gnm_expr_new_binary (make_cellref (0,-4), GNM_EXPR_OP_SUB,
+							       gnm_expr_new_constant (value_new_int (1))));
+	expr = gnm_expr_new_funcall1 
+		(fd_eigen, gnm_expr_new_binary 
+		 (expr_count, GNM_EXPR_OP_MULT, make_rangeref (0, - (5 + l), l - 1, - 6)));
+	dao_set_array_expr (dao, 1, 7 + l, l, l + 1, expr);
+
+	for (i = 1; i <= l; i++) {
+		dao_set_align (dao, i, 9 + 2 * l, i, 9 + 2 * l,
+			       HALIGN_CENTER, VALIGN_BOTTOM);
+		dao_set_cell_printf (dao, i, 9 + 2 * l, "\xce\xbe%i", i);
+		dao_set_cell_expr (dao, i, 11 + 3 * l, 
+				   gnm_expr_new_binary (make_cellref (0,- 4 - 2 * l),
+							GNM_EXPR_OP_DIV,
+							gnm_expr_new_funcall1 
+							(fd_sum,
+							 dao_get_rangeref (dao, 1, 7 + l, l, 7 + l))));
+	}
+
+	expr_munit =  gnm_expr_new_funcall1 (fd_munit, gnm_expr_new_constant (value_new_int (l)));
+	expr = gnm_expr_new_funcall2 (fd_mmult,
+				      gnm_expr_new_binary 
+				      (gnm_expr_new_funcall1 
+				       (fd_sqrt, gnm_expr_new_binary 
+					(gnm_expr_new_constant (value_new_int (1)),
+					 GNM_EXPR_OP_DIV, 
+					 make_rangeref (0, - 5 - l, l - 1, - 5 - l))),
+				       GNM_EXPR_OP_MULT,
+				       gnm_expr_copy (expr_munit)),
+				      make_rangeref (0, - 2 - l, l - 1, - 3));
+	expr = gnm_expr_new_funcall2 (fd_mmult, expr,
+				      gnm_expr_new_binary 
+				      (gnm_expr_new_funcall1 
+				       (fd_sqrt, make_rangeref (0, - 3 - l, l - 1, - 3 - l)),
+				       GNM_EXPR_OP_MULT,
+				       expr_munit));
+	dao_set_array_expr (dao, 1, 10 + 2 * l, l, l, expr);
+
+	gnm_func_unref (fd_mean);
+	gnm_func_unref (fd_var);
+	gnm_func_unref (fd_eigen);
+	gnm_func_unref (fd_mmult);
+	gnm_func_unref (fd_munit);
+	gnm_func_unref (fd_sqrt);
+	gnm_func_unref (fd_count);
+	gnm_func_unref (fd_sum);
+	gnm_func_unref (fd_and);
+	gnm_func_unref (fd_if);
+
+	dao_redraw_respan (dao);
+	return 0;
+}
+
+gboolean
+analysis_tool_principal_components_engine (data_analysis_output_t *dao, gpointer specs,
+				   analysis_tool_engine_t selector, gpointer result)
+{
+	analysis_tools_data_generic_t *info = specs;
+
+	switch (selector) {
+	case TOOL_ENGINE_UPDATE_DESCRIPTOR:
+		return (dao_command_descriptor 
+			(dao, _("Principal Components Analysis (%s)"), result)
+			== NULL);
+	case TOOL_ENGINE_UPDATE_DAO:
+		prepare_input_range (&info->input, info->group_by);
+		dao_adjust (dao, 1 + g_slist_length (info->input),
+			    12 + 3 * g_slist_length (info->input));
+		return FALSE;
+	case TOOL_ENGINE_CLEAN_UP:
+		return analysis_tool_generic_clean (specs);
+	case TOOL_ENGINE_LAST_VALIDITY_CHECK:
+		return FALSE;
+	case TOOL_ENGINE_PREPARE_OUTPUT_RANGE:
+		dao_prepare_output (NULL, dao, _("Principal Components Analysis"));
+		return FALSE;
+	case TOOL_ENGINE_FORMAT_OUTPUT_RANGE:
+		return dao_format_output (dao, _("Principal Components Analysis"));
+	case TOOL_ENGINE_PERFORM_CALC:
+	default:
+		return analysis_tool_principal_components_engine_run (dao, specs);
+	}
+	return TRUE;  /* We shouldn't get here */
+}
diff --git a/src/tools/analysis-principal-components.h b/src/tools/analysis-principal-components.h
new file mode 100644
index 0000000..9458335
--- /dev/null
+++ b/src/tools/analysis-principal-components.h
@@ -0,0 +1,41 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * analysis-principal-components.h:
+ *
+ * Author:
+ *   Andreas J. Guelzow  <aguelzow pyrshep ca>
+ *
+ * (C) Copyright 2009 by Andreas J. Guelzow  <aguelzow pyrshep ca>
+ *
+ *
+ * This program 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifndef ANALYSIS_PRINCIPAL_COMPONENTS_H
+#define ANALYSIS_PRINCIPAL_COMPONENTS_H
+
+#include "gnumeric.h"
+#include "numbers.h"
+#include "dao.h"
+#include "tools.h"
+#include "analysis-tools.h"
+#include "sheet.h"
+
+gboolean analysis_tool_principal_components_engine (data_analysis_output_t *dao, gpointer specs,
+					   analysis_tool_engine_t selector, gpointer result);
+
+
+#endif
diff --git a/src/tools/analysis-tools.c b/src/tools/analysis-tools.c
index b4416e3..0a65eb6 100644
--- a/src/tools/analysis-tools.c
+++ b/src/tools/analysis-tools.c
@@ -539,18 +539,19 @@ int analysis_tool_calc_length (analysis_tools_data_generic_t *info)
  *
  **/
 
-static gboolean
+gboolean
 analysis_tool_table (data_analysis_output_t *dao,
 		     analysis_tools_data_generic_t *info,
-		     gchar const *title, gchar const *functionname)
+		     gchar const *title, gchar const *functionname,
+		     gboolean full_table)
 {
 	GSList *inputdata, *inputexpr = NULL;
 	GnmFunc *fd = NULL;
 
 	guint col, row;
 
-	dao_set_cell_printf (dao, 0, 0, "%s", title);
 	dao_set_italic (dao, 0, 0, 0, 0);
+	dao_set_cell_printf (dao, 0, 0, "%s", title);
 
 	fd = gnm_func_lookup_or_add_placeholder (functionname, dao->sheet ? dao->sheet->workbook : NULL, FALSE);
 	gnm_func_ref (fd);
@@ -584,7 +585,7 @@ analysis_tool_table (data_analysis_output_t *dao,
 		     colexprlist = colexprlist->next, col++) {
 			GnmExpr const *colexpr = colexprlist->data;
 
-			if (col < row)
+			if ((!full_table) && (col < row))
 				continue;
 
 			dao_set_cell_expr
@@ -610,7 +611,8 @@ static gboolean
 analysis_tool_correlation_engine_run (data_analysis_output_t *dao,
 				      analysis_tools_data_generic_t *info)
 {
-	return analysis_tool_table (dao, info, _("Correlations"), "CORREL");
+	return analysis_tool_table (dao, info, _("Correlations"), 
+				    "CORREL", FALSE);
 }
 
 gboolean
@@ -664,7 +666,8 @@ static gboolean
 analysis_tool_covariance_engine_run (data_analysis_output_t *dao,
 				      analysis_tools_data_generic_t *info)
 {
-	return analysis_tool_table (dao, info, _("Covariances"), "COVAR");
+	return analysis_tool_table (dao, info, _("Covariances"), 
+				    "COVAR", FALSE);
 }
 
 gboolean
diff --git a/src/tools/analysis-tools.h b/src/tools/analysis-tools.h
index 6248b35..b5a4af5 100644
--- a/src/tools/analysis-tools.h
+++ b/src/tools/analysis-tools.h
@@ -215,6 +215,11 @@ void analysis_tools_write_label (GnmValue *val, data_analysis_output_t *dao,
 void analysis_tools_write_label_ftest (GnmValue *val, data_analysis_output_t *dao,
 				       int x, int y, gboolean labels, int i);
 
+gboolean analysis_tool_table (data_analysis_output_t *dao,
+			      analysis_tools_data_generic_t *info,
+			      gchar const *title, gchar const *functionname,
+			      gboolean full_table);
+
 void prepare_input_range (GSList **input_range, group_by_t group_by);
 
 const GnmExpr *make_cellref (int dx, int dy);
diff --git a/src/wbc-gtk-actions.c b/src/wbc-gtk-actions.c
index 4b0cea0..258360d 100644
--- a/src/wbc-gtk-actions.c
+++ b/src/wbc-gtk-actions.c
@@ -880,6 +880,7 @@ static GNM_ACTION_DEF (cb_tools_frequency)	{ dialog_frequency_tool (wbcg, wbcg_c
 static GNM_ACTION_DEF (cb_tools_histogram)	{ dialog_histogram_tool (wbcg, wbcg_cur_sheet (wbcg)); }
 static GNM_ACTION_DEF (cb_tools_kaplan_meier)	{ dialog_kaplan_meier_tool (wbcg, wbcg_cur_sheet (wbcg)); }
 static GNM_ACTION_DEF (cb_tools_normality_tests){ dialog_normality_tool (wbcg, wbcg_cur_sheet (wbcg)); }
+static GNM_ACTION_DEF (cb_tools_principal_components)	{ dialog_principal_components_tool (wbcg, wbcg_cur_sheet (wbcg)); }
 static GNM_ACTION_DEF (cb_tools_ranking)	{ dialog_ranking_tool (wbcg, wbcg_cur_sheet (wbcg)); }
 static GNM_ACTION_DEF (cb_tools_regression)	{ dialog_regression_tool (wbcg, wbcg_cur_sheet (wbcg)); }
 static GNM_ACTION_DEF (cb_tools_sampling)	{ dialog_sampling_tool (wbcg, wbcg_cur_sheet (wbcg)); }
@@ -2124,6 +2125,10 @@ static GtkActionEntry const actions[] = {
 	{ "ToolsFourier", NULL, N_("_Fourier Analysis..."),
 		NULL, N_("Fourier Analysis"),
 		G_CALLBACK (cb_tools_fourier) },
+	{ "ToolsPrincipalComponents", NULL, 
+	        N_("Principal Components Analysis..."),
+		NULL, N_("Principal Components Analysis"),
+		G_CALLBACK (cb_tools_principal_components) },
 	{ "ToolsRanking", NULL, N_("Ranks And _Percentiles..."),
 		NULL, N_("Ranks, placements and percentiles"),
 		G_CALLBACK (cb_tools_ranking) },



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]