Commit 6b1a937a authored by Jukka-Pekka Iivonen's avatar Jukka-Pekka Iivonen Committed by jpekka

Gladefied the Solver tool. Implemented `Change' (constraint) button.

2000-01-31  Jukka-Pekka Iivonen  <iivonen@iki.fi>

	* src/dialogs/dialog-solver.c, src/dialogs/solver.glade,
 	src/dialogs/Makefile.am: Gladefied the Solver tool.  Implemented
 	`Change' (constraint) button.

	* src/functions/fn-math.c: Added RandExp(), RandPoisson(),
 	RandBinom(), RandNegBinom(), and RandBernoulli() functions.

	* src/functions/fn-math.c, src/mathfunc.[ch]: Moved gcd to
 	mathfunc.c.
parent a038ab94
2000-01-31 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/dialogs/dialog-solver.c, src/dialogs/solver.glade,
src/dialogs/Makefile.am: Gladefied the Solver tool. Implemented
`Change' (constraint) button.
* src/functions/fn-math.c: Added RandExp(), RandPoisson(),
RandBinom(), RandNegBinom(), and RandBernoulli() functions.
* src/functions/fn-math.c, src/mathfunc.[ch]: Moved gcd to
mathfunc.c.
2000-01-31 Jody Goldberg <jgoldberg@home.com>
* src/worksheet.h : Move more of the pure view elements into
......
......@@ -13,6 +13,8 @@ Jukka:
- Exponential
* Minor improvements for the AutoSave tool.
* GUI improvements for the Data Analysis tool.
* Added RandExp(), RandPoisson(), RandBinom(), RandNegBinom(),
and RandBernoulli() functions.
Jody:
* Row/Col header redraw improvements.
......
2000-01-31 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/dialogs/dialog-solver.c, src/dialogs/solver.glade,
src/dialogs/Makefile.am: Gladefied the Solver tool. Implemented
`Change' (constraint) button.
* src/functions/fn-math.c: Added RandExp(), RandPoisson(),
RandBinom(), RandNegBinom(), and RandBernoulli() functions.
* src/functions/fn-math.c, src/mathfunc.[ch]: Moved gcd to
mathfunc.c.
2000-01-31 Jody Goldberg <jgoldberg@home.com>
* src/worksheet.h : Move more of the pure view elements into
......
......@@ -14,22 +14,6 @@
#include "collect.h"
#include "auto-format.h"
static int
gcd (int a, int b)
{
/* Euclid's Algorithm. Assumes non-negative numbers. */
while (b != 0) {
int r;
r = a - (a / b) * b; /* r = remainder from
* dividing a by b */
a = b;
b = r;
}
return a;
}
typedef struct {
GSList *list;
......@@ -1278,6 +1262,144 @@ gnumeric_rand (FunctionEvalInfo *ei, Value **argv)
/***************************************************************************/
static char *help_randexp = {
N_("@FUNCTION=RandExp\n"
"@SYNTAX=RandExp(b)\n"
"@DESCRIPTION="
"RandExp returns a exponentially distributed random number. "
"\n"
"@EXAMPLES=\n"
"RandExp(0.5).\n"
"\n"
"@SEEALSO=RAND,RANDBETWEEN")
};
static Value *
gnumeric_randexp (FunctionEvalInfo *ei, Value **argv)
{
float_t x = value_get_as_float (argv[0]);
return value_new_float (random_exponential (x));
}
/***************************************************************************/
static char *help_randpoisson = {
N_("@FUNCTION=RandPoisson\n"
"@SYNTAX=RandPoisson(lambda)\n"
"@DESCRIPTION="
"RandPoisson returns a poisson distributed random number. "
"\n"
"@EXAMPLES=\n"
"RandPoisson(3).\n"
"\n"
"@SEEALSO=RAND,RANDBETWEEN")
};
static Value *
gnumeric_randpoisson (FunctionEvalInfo *ei, Value **argv)
{
float_t x = value_get_as_float (argv[0]);
if (x < 0)
return value_new_error (ei->pos, gnumeric_err_NUM);
return value_new_float (random_poisson (x));
}
/***************************************************************************/
static char *help_randbinom = {
N_("@FUNCTION=RandBinom\n"
"@SYNTAX=RandBinom(p,trials)\n"
"@DESCRIPTION="
"RandBinom returns a binomialy distributed random number. "
"\n"
"If @p < 0 or @p > 1 RandBinom returns #NUM! error. "
"If @trials < 0 RandBinom returns #NUM! error. "
"\n"
"@EXAMPLES=\n"
"RandBinom(0.5,2).\n"
"\n"
"@SEEALSO=RAND,RANDBETWEEN")
};
static Value *
gnumeric_randbinom (FunctionEvalInfo *ei, Value **argv)
{
float_t p = value_get_as_float (argv[0]);
int trials = value_get_as_int (argv[1]);
if (p < 0 || p > 1 || trials < 0)
return value_new_error (ei->pos, gnumeric_err_NUM);
return value_new_float (random_binomial (p, trials));
}
/***************************************************************************/
static char *help_randnegbinom = {
N_("@FUNCTION=RandNegBinom\n"
"@SYNTAX=RandNegBinom(p,failures)\n"
"@DESCRIPTION="
"RandNegBinom returns a negitive binomialy distributed random "
"number. "
"\n"
"If @p < 0 or @p > 1 RandNegBinom returns #NUM! error. "
"If @failures RandNegBinom returns #NUM! error. "
"\n"
"@EXAMPLES=\n"
"RandNegBinom(0.5,2).\n"
"\n"
"@SEEALSO=RAND,RANDBETWEEN")
};
static Value *
gnumeric_randnegbinom (FunctionEvalInfo *ei, Value **argv)
{
float_t p = value_get_as_float (argv[0]);
int failures = value_get_as_int (argv[1]);
if (p < 0 || p > 1 || failures < 0)
return value_new_error (ei->pos, gnumeric_err_NUM);
return value_new_float (random_negbinom (p, failures));
}
/***************************************************************************/
static char *help_randbernoulli = {
N_("@FUNCTION=RandBernoulli\n"
"@SYNTAX=RandBernoulli(p)\n"
"@DESCRIPTION="
"RandBernoulli returns a Bernoulli distributed random number. "
"\n"
"If @p < 0 or @p > 1 RandBernoulli returns #NUM! error. "
"\n"
"@EXAMPLES=\n"
"RandBernoulli(0.5).\n"
"\n"
"@SEEALSO=RAND,RANDBETWEEN")
};
static Value *
gnumeric_randbernoulli (FunctionEvalInfo *ei, Value **argv)
{
float_t p = value_get_as_float (argv[0]);
if (p < 0 || p > 1)
return value_new_error (ei->pos, gnumeric_err_NUM);
return value_new_float (random_bernoulli (p));
}
/***************************************************************************/
static char *help_sin = {
N_("@FUNCTION=SIN\n"
"@SYNTAX=SIN(x)\n"
......@@ -3465,9 +3587,24 @@ math_functions_init (void)
gnumeric_radians);
function_add_args (cat, "rand", "",
"", &help_rand, gnumeric_rand);
function_add_args (cat, "randbetween", "ff",
"bottom,top",
&help_randbetween, gnumeric_randbetween);
function_add_args (cat, "randbernoulli", "f",
"p",
&help_randbernoulli, gnumeric_randbernoulli);
function_add_args (cat, "randbetween", "ff",
"bottom,top",
&help_randbetween, gnumeric_randbetween);
function_add_args (cat, "randbinom", "ff",
"p,trials",
&help_randbinom, gnumeric_randbinom);
function_add_args (cat, "randexp", "f",
"b",
&help_randexp, gnumeric_randexp);
function_add_args (cat, "randnegbinom", "ff",
"p,failures",
&help_randnegbinom, gnumeric_randnegbinom);
function_add_args (cat, "randpoisson", "f",
"lambda",
&help_randpoisson, gnumeric_randpoisson);
function_add_args (cat, "roman", "f|f",
"number[,type]",
&help_roman, gnumeric_roman);
......
......@@ -61,17 +61,18 @@ INSTOBJEXT = @INSTOBJEXT@
.c.o:
$(COMPILE) $<
%.pox: %.po $(srcdir)/$(PACKAGE).pot
.po.pox:
$(MAKE) $(PACKAGE).pot
$(MSGMERGE) $< $(srcdir)/$(PACKAGE).pot -o $*.pox
%.mo: %.po
.po.mo:
$(MSGFMT) -o $@ $<
%.gmo: %.po
.po.gmo:
file=$(srcdir)/`echo $* | sed 's,.*/,,'`.gmo \
&& rm -f $$file && $(GMSGFMT) -o $$file $<
%.cat: %.po
.po.cat:
sed -f ../intl/po2msg.sed < $< > $*.msg \
&& rm -f $@ && $(GENCAT) $@ $*.msg
......@@ -90,7 +91,7 @@ $(srcdir)/$(PACKAGE).pot: $(POTFILES)
&& mv $(PACKAGE).po $(srcdir)/$(PACKAGE).pot )
$(srcdir)/cat-id-tbl.c: stamp-cat-id; @:
$(srcdir)/stamp-cat-id: $(srcdir)/$(PACKAGE).pot
$(srcdir)/stamp-cat-id: $(PACKAGE).pot
rm -f cat-id-tbl.tmp
sed -f ../intl/po2tbl.sed $(srcdir)/$(PACKAGE).pot \
| sed -e "s/@PACKAGE NAME@/$(PACKAGE)/" > cat-id-tbl.tmp
......@@ -205,7 +206,8 @@ dist distdir: update-po $(DISTFILES)
|| cp -p $(srcdir)/$$file $(distdir); \
done
update-po: Makefile $(srcdir)/$(PACKAGE).pot
update-po: Makefile
$(MAKE) $(PACKAGE).pot
PATH=`pwd`/../src:$$PATH; \
cd $(srcdir); \
catalogs='$(CATALOGS)'; \
......
......@@ -60,6 +60,7 @@ glade_DATA = \
print.glade \
row-height.glade \
sheet-rename.glade \
solver.glade \
solver-options.glade \
summary.glade \
dialog-zoom.glade \
......
......@@ -30,36 +30,6 @@ static const char *constraint_strs[] = {
};
static const char *equal_ops [] = {
N_("Max"),
N_("Min"),
NULL
};
static GSList *
add_radio_buttons (GtkWidget *hbox, const char *title, const char *ops[])
{
GtkWidget *f, *fv;
GSList *group_ops = NULL;
int i;
f = gtk_frame_new (_(title));
fv = gtk_vbox_new (TRUE, 0);
gtk_container_add (GTK_CONTAINER (f), fv);
for (i = 0; ops [i]; i++) {
GtkWidget *r;
r = gtk_radio_button_new_with_label (group_ops, ops [i]);
group_ops = GTK_RADIO_BUTTON (r)->group;
gtk_box_pack_start_defaults (GTK_BOX (fv), r);
}
gtk_box_pack_start_defaults (GTK_BOX (hbox), f);
return group_ops;
}
typedef struct {
GtkWidget *dialog;
......@@ -153,26 +123,15 @@ add_constraint(constraint_dialog_t *constraint_dialog,
char *constraint_str[2] = { constraint_buf, NULL };
gint row;
sprintf(constraint_buf, "%s %s ",
cell_name (lhs_col, lhs_row),
sprintf(constraint_buf, "%s %s ", cell_name (lhs_col, lhs_row),
type_str);
strcat(constraint_buf, cell_name(rhs_col, rhs_row));
constraint = g_new (SolverConstraint, 1);
constraint->lhs = sheet_cell_get (constraint_dialog->sheet,
lhs_col, lhs_row);
if (constraint->lhs == NULL) {
cell_error:
gnumeric_notice (constraint_dialog->wb,
GNOME_MESSAGE_BOX_ERROR,
_("You gave a cell reference that contain "
"no data."));
return 1;
}
constraint->rhs = sheet_cell_get (constraint_dialog->sheet,
rhs_col, rhs_row);
if (constraint->rhs == NULL)
goto cell_error;
constraint->lhs_col = lhs_col;
constraint->lhs_row = lhs_row;
constraint->rhs_col = rhs_col;
constraint->rhs_row = rhs_row;
row = gtk_clist_append (constraint_dialog->clist, constraint_str);
constraint->type = g_malloc (strlen (type_str) + 1);
......@@ -190,59 +149,52 @@ add_constraint(constraint_dialog_t *constraint_dialog,
/* 'Constraint Add' button clicked */
static void
constr_add_click (gpointer data)
constr_add_click (constraint_dialog_t *constraint_dialog)
{
static GtkWidget *dialog;
static GtkWidget *lhs_entry;
static GtkWidget *rhs_entry;
static GtkWidget *type_entry;
static GList *constraint_type_strs;
constraint_dialog_t *constraint_dialog = (constraint_dialog_t *) data;
int selection;
char *lhs_text, *rhs_text;
int rhs_col, rhs_row;
int lhs_col, lhs_row;
char *type_str;
gtk_widget_hide (constraint_dialog->dialog);
if (!dialog) {
GtkWidget *box;
constraint_type_strs = add_strings_to_glist (constraint_strs);
dialog = gnome_dialog_new (_("Add Constraint"),
GNOME_STOCK_BUTTON_OK,
GNOME_STOCK_BUTTON_CANCEL,
_("Add"),
NULL);
gnome_dialog_close_hides (GNOME_DIALOG (dialog), TRUE);
box = gtk_hbox_new (FALSE, 0);
GladeXML *gui = glade_xml_new (GNUMERIC_GLADEDIR "/solver.glade",
NULL);
GtkWidget *dialog;
GtkWidget *lhs_entry;
GtkWidget *rhs_entry;
GtkWidget *type_entry;
GtkWidget *combo_entry;
GList *constraint_type_strs;
int selection;
char *lhs_text, *rhs_text;
int rhs_col, rhs_row;
int lhs_col, lhs_row;
char *type_str;
lhs_entry = hbox_pack_label_and_entry
("Left Hand Side:", "", 20, box);
if (!gui) {
printf ("Could not find solver.glade\n");
return;
}
constraint_type_strs = add_strings_to_glist (constraint_strs);
type_entry = gtk_combo_new ();
gtk_combo_set_popdown_strings (GTK_COMBO (type_entry),
constraint_type_strs);
gtk_box_pack_start_defaults (GTK_BOX (box), type_entry);
dialog = glade_xml_get_widget (gui, "SolverAddConstraint");
lhs_entry = glade_xml_get_widget (gui, "entry1");
rhs_entry = glade_xml_get_widget (gui, "entry2");
type_entry = glade_xml_get_widget (gui, "combo1");
combo_entry = glade_xml_get_widget (gui, "combo-entry1");
rhs_entry = hbox_pack_label_and_entry
("Right Hand Side:", "", 20, box);
if (!dialog || !lhs_entry || !rhs_entry ||
!type_entry || !combo_entry) {
printf ("Corrupt file solver.glade\n");
return;
}
gtk_box_pack_start_defaults (GTK_BOX (GNOME_DIALOG
(dialog)->vbox), box);
gtk_combo_set_popdown_strings (GTK_COMBO (type_entry),
constraint_type_strs);
gtk_widget_show_all (dialog);
} else
gtk_widget_show (dialog);
gtk_widget_hide (constraint_dialog->dialog);
add_dialog:
gtk_widget_grab_focus (lhs_entry);
/* Run the dialog */
gtk_widget_grab_focus (lhs_entry);
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
selection = gnumeric_dialog_run (constraint_dialog->wb,
GNOME_DIALOG (dialog));
......@@ -282,7 +234,10 @@ add_dialog:
if (selection == 2)
goto add_dialog;
gnome_dialog_close (GNOME_DIALOG (dialog));
if (selection != -1)
gtk_object_destroy (GTK_OBJECT (dialog));
gtk_object_unref (GTK_OBJECT (gui));
gtk_widget_show (constraint_dialog->dialog);
}
......@@ -290,9 +245,128 @@ static gint selected_row = -1;
/* 'Constraint Change' button clicked */
static void
constr_change_click (gpointer data)
constr_change_click (constraint_dialog_t *data)
{
printf("Change: Not implemented yet.\n");
SolverConstraint *constraint;
GladeXML *gui = glade_xml_new (GNUMERIC_GLADEDIR "/solver.glade",
NULL);
GtkWidget *dia;
GtkWidget *lhs_entry;
GtkWidget *rhs_entry;
GtkWidget *type_combo;
GtkWidget *combo_entry;
GList *constraint_type_strs;
gint v;
gchar *txt, *entry;
int col, row;
if (selected_row < 0)
return;
if (!gui) {
printf ("Could not find solver.glade\n");
return;
}
constraint_type_strs = add_strings_to_glist (constraint_strs);
dia = glade_xml_get_widget (gui, "SolverChangeConstraint");
lhs_entry = glade_xml_get_widget (gui, "entry3");
rhs_entry = glade_xml_get_widget (gui, "entry4");
type_combo = glade_xml_get_widget (gui, "combo2");
combo_entry = glade_xml_get_widget (gui, "combo-entry2");
if (!dia || !lhs_entry || !rhs_entry || !type_combo || !combo_entry) {
printf ("Corrupt file solver.glade\n");
return;
}
gtk_combo_set_popdown_strings (GTK_COMBO (type_combo),
constraint_type_strs);
constraint = (SolverConstraint *)
gtk_clist_get_row_data (data->clist, selected_row);
gtk_entry_set_text (GTK_ENTRY (lhs_entry),
cell_name (constraint->lhs_col,
constraint->lhs_row));
gtk_entry_set_text (GTK_ENTRY (rhs_entry),
cell_name (constraint->rhs_col,
constraint->rhs_row));
gtk_entry_set_text (GTK_ENTRY (combo_entry), constraint->type);
gtk_widget_hide (data->dialog);
gtk_entry_set_position(GTK_ENTRY (lhs_entry), 0);
gtk_entry_select_region(GTK_ENTRY (lhs_entry), 0,
GTK_ENTRY(lhs_entry)->text_length);
/* Run the dialog */
gtk_widget_grab_focus (lhs_entry);
gtk_window_set_modal (GTK_WINDOW (dia), TRUE);
loop:
v = gnumeric_dialog_run (data->wb, GNOME_DIALOG (dia));
if (v == 0) {
gchar buf[512];
gchar *constraint_str[2] = { buf, NULL };
entry = gtk_entry_get_text (GTK_ENTRY (lhs_entry));
txt = (gchar *) cell_name (constraint->lhs_col,
constraint->lhs_row);
if (strcmp (entry, txt) != 0) {
if (!parse_cell_name (entry, &col, &row)) {
gtk_widget_grab_focus (lhs_entry);
gtk_entry_set_position(GTK_ENTRY (lhs_entry),
0);
gtk_entry_select_region(GTK_ENTRY (lhs_entry),
0,
GTK_ENTRY(lhs_entry)->
text_length);
goto loop;
}
constraint->lhs_col = col;
constraint->lhs_row = row;
}
entry = gtk_entry_get_text (GTK_ENTRY (rhs_entry));
txt = (gchar *) cell_name (constraint->rhs_col,
constraint->rhs_row);
if (strcmp (entry, txt) != 0) {
if (!parse_cell_name (entry, &col, &row)) {
gtk_widget_grab_focus (rhs_entry);
gtk_entry_set_position(GTK_ENTRY (rhs_entry),
0);
gtk_entry_select_region(GTK_ENTRY (rhs_entry),
0,
GTK_ENTRY(rhs_entry)->
text_length);
goto loop;
}
constraint->rhs_col = col;
constraint->rhs_row = row;
}
entry = gtk_entry_get_text (GTK_ENTRY (combo_entry));
g_free (constraint->type);
constraint->type = g_malloc (strlen (entry) + 1);
strcpy (constraint->type, entry);
g_free (constraint->str);
sprintf(buf, "%s %s ", cell_name (constraint->lhs_col,
constraint->lhs_row), entry);
strcat (buf, cell_name(constraint->rhs_col,
constraint->rhs_row));
constraint->str = g_malloc (strlen (buf)+1);
strcpy (constraint->str, buf);
gtk_clist_remove (data->clist, selected_row);
gtk_clist_insert (data->clist, selected_row, constraint_str);
gtk_clist_set_row_data (data->clist, selected_row,
(gpointer) constraint);
}
if (v != -1)
gtk_object_destroy (GTK_OBJECT (dia));
gtk_object_unref (GTK_OBJECT (gui));
gtk_widget_show (data->dialog);
}
......@@ -313,7 +387,6 @@ constr_delete_click (gpointer data)
}
}
static void
constraint_select_click (GtkWidget *clist,
gint row,
......@@ -324,142 +397,135 @@ constraint_select_click (GtkWidget *clist,
selected_row = row;
}
static void
max_toggled(GtkWidget *widget, SolverParameters *data)
{
if (GTK_TOGGLE_BUTTON (widget)->active) {
data->problem_type = SolverMaximize;
}
}
static void
min_toggled(GtkWidget *widget, SolverParameters *data)
{
if (GTK_TOGGLE_BUTTON (widget)->active) {
data->problem_type = SolverMinimize;