> I'm not sure how to add the variables.

I am. :-)

> I've patched 7.1.386 with the new floating point patch.

326 perhaps?

> The attached patch to that includes log, exp, sin, cos, tan,
> asin, acos, atan and atan2.

OK, here's a counter-patch, including documentation, which is the bigger
task, I think. It includes all my suggestions, as well as Bill's work,
plus a couple of other things that have been suggested/that I noticed:

- New variables: v:inf, v:nan, v:e, v:pi.
- New functions: abs, acos, asin, atan, atan2, cos, cosh, deg2rad, exp,
   log, rad2deg, sin, sinh, tan, tanh.
- Change division by zero behaviour for Numbers to match what float2nr()
   does.
- Fixes get_float_arg so it's inside #ifdef FEAT_FLOAT and you can still
   compile without float support!
- Documentation for new variables, new functions, float and altered
   Number division by zero behaviour, float precision, another pow()
   example, and more conspicuous noting of the use of str2float as
   nr2float. Fix in alphabetical order in a list, too. I noticed also
   that only using %e can you be sure of getting maximum precision. %g
   you can in some situations get more or less shown than you want.

> Caution - it's DOS format and is applied from the src
> directory.

This one is in Unix format and applies from the root of the source tree
with -p1. It goes on top of 7.1.326 and Bram's floating point patch.

So at least this won't take any signficant amount of Bram's time, now. We just 
have to convince him about what are the best parts of it to include!

I suggest:
   - We could easily do without: cosh, sinh, tanh (they are simple to
     implement with scripts and rarely used).
   - We could probably do without: v:inf, v:nan, v:e, v:pi, exp, log,
     tan, deg2rad, rad2deg (simple to implement with scripts, but they
     are convenient and common so worth keeping, particularly the last
     two, which make sin, cos and atan much more useful).
   - We could probably do without: asin, acos, atan2 (but implementing
     them with script, although possible, is quite a lot of pain, so I
     would suggest keeping them, even though they are more rare).
   - The rest of the functional changes have either already been agreed
     to or I personally deem to be pretty much essential.

By the way, Bram, I am getting warnings when compiling on the Mac about
MAXPATHL being redefined. It is defined at os_mac.h:222 and
os_unix.h:438, which are evidently both included. I think simply
removing line os_mac.h:222 will correctly fix it.

Ben.




--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---

diff -r 41941dee5dd7 src/eval.c
--- a/src/eval.c	Sat Jun 21 02:54:51 2008 +1000
+++ b/src/eval.c	Sat Jun 21 20:38:02 2008 +1000
@@ -351,6 +351,17 @@
     {VV_NAME("mouse_lnum",	 VAR_NUMBER), 0},
     {VV_NAME("mouse_col",	 VAR_NUMBER), 0},
     {VV_NAME("operator",	 VAR_STRING), VV_RO},
+#ifdef FEAT_FLOAT
+    {VV_NAME("inf",		 VAR_FLOAT), VV_RO},
+    {VV_NAME("nan",		 VAR_FLOAT), VV_RO},
+    {VV_NAME("e",		 VAR_FLOAT), VV_RO},
+    {VV_NAME("pi",		 VAR_FLOAT), VV_RO},
+#else
+    {VV_NAME("inf",		 VAR_NUMBER), VV_RO},
+    {VV_NAME("nan",		 VAR_NUMBER), VV_RO},
+    {VV_NAME("e",		 VAR_NUMBER), VV_RO},
+    {VV_NAME("pi",		 VAR_NUMBER), VV_RO},
+#endif
 };
 
 /* shorthand */
@@ -466,11 +477,20 @@
 static int call_func __ARGS((char_u *name, int len, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));
 static void emsg_funcname __ARGS((char *ermsg, char_u *name));
 
+static void f_abs __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_FLOAT
+static void f_acos __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
 static void f_add __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_append __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_argc __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_argidx __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_argv __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_FLOAT
+static void f_asin __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_atan __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_atan2 __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
 static void f_browse __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_browsedir __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_bufexists __ARGS((typval_T *argvars, typval_T *rettv));
@@ -497,10 +517,17 @@
 #endif
 static void f_confirm __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_copy __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_FLOAT
+static void f_cos __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_cosh __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
 static void f_count __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_cscope_connection __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_cursor __ARGS((typval_T *argsvars, typval_T *rettv));
 static void f_deepcopy __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_FLOAT
+static void f_deg2rad __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
 static void f_delete __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_did_filetype __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_diff_filler __ARGS((typval_T *argvars, typval_T *rettv));
@@ -511,6 +538,9 @@
 static void f_eventhandler __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_executable __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_exists __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_FLOAT
+static void f_exp __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
 static void f_expand __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_extend __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_feedkeys __ARGS((typval_T *argvars, typval_T *rettv));
@@ -597,6 +627,7 @@
 static void f_localtime __ARGS((typval_T *argvars, typval_T *rettv));
 #ifdef FEAT_FLOAT
 static void f_log10 __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_log __ARGS((typval_T *argvars, typval_T *rettv));
 #endif
 static void f_map __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_maparg __ARGS((typval_T *argvars, typval_T *rettv));
@@ -627,6 +658,9 @@
 static void f_readfile __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_reltime __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_reltimestr __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_FLOAT
+static void f_rad2deg __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
 static void f_remote_expr __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_remote_foreground __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_remote_peek __ARGS((typval_T *argvars, typval_T *rettv));
@@ -660,6 +694,10 @@
 static void f_setwinvar __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_shellescape __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_simplify __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_FLOAT
+static void f_sin __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_sinh __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
 static void f_sort __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_soundfold __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_spellbadword __ARGS((typval_T *argvars, typval_T *rettv));
@@ -691,6 +729,10 @@
 static void f_tabpagewinnr __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_taglist __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_tagfiles __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_FLOAT
+static void f_tan __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_tanh __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
 static void f_tempname __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_test __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_tolower __ARGS((typval_T *argvars, typval_T *rettv));
@@ -822,6 +864,17 @@
 	    /* add to compat scope dict */
 	    hash_add(&compat_hashtab, p->vv_di.di_key);
     }
+#ifdef FEAT_FLOAT
+    vimvars[VV_INF].vv_float = 1.0 / 0.0;
+    vimvars[VV_NAN].vv_float = 0.0 / 0.0;
+    vimvars[VV_E].vv_float = 2.718281828459045;
+    vimvars[VV_PI].vv_float = 3.141592653589793;
+#else
+    vimvars[VV_INF].vv_nr = 0x7fffffffL;
+    vimvars[VV_NAN].vv_nr = -0x7fffffffL-1;
+    vimvars[VV_E].vv_nr = 2;
+    vimvars[VV_PI].vv_nr = 3;
+#endif
 }
 
 #if defined(EXITFREE) || defined(PROTO)
@@ -4728,7 +4781,12 @@
 		else if (op == '/')
 		{
 		    if (n2 == 0)	/* give an error message? */
-			n1 = 0x7fffffffL;
+			if (n1 == 0)
+			    n1 = -0x7fffffffL-1;
+			else if (n1 < 0)
+			    n1 = -0x7fffffffL;
+			else
+			    n1 = 0x7fffffffL;
 		    else
 			n1 = n1 / n2;
 		}
@@ -7386,11 +7444,20 @@
 				/* implementation of function */
 } functions[] =
 {
+    {"abs",		1, 1, f_abs},
+#ifdef FEAT_FLOAT
+    {"acos",		1, 1, f_acos},
+#endif
     {"add",		2, 2, f_add},
     {"append",		2, 2, f_append},
     {"argc",		0, 0, f_argc},
     {"argidx",		0, 0, f_argidx},
     {"argv",		0, 1, f_argv},
+#ifdef FEAT_FLOAT
+    {"asin",		1, 1, f_asin},
+    {"atan",		1, 1, f_atan},
+    {"atan2",		2, 2, f_atan2},
+#endif
     {"browse",		4, 4, f_browse},
     {"browsedir",	2, 2, f_browsedir},
     {"bufexists",	1, 1, f_bufexists},
@@ -7420,10 +7487,17 @@
 #endif
     {"confirm",		1, 4, f_confirm},
     {"copy",		1, 1, f_copy},
+#ifdef FEAT_FLOAT
+    {"cos",		1, 1, f_cos},
+    {"cosh",		1, 1, f_cosh},
+#endif
     {"count",		2, 4, f_count},
     {"cscope_connection",0,3, f_cscope_connection},
     {"cursor",		1, 3, f_cursor},
     {"deepcopy",	1, 2, f_deepcopy},
+#ifdef FEAT_FLOAT
+    {"deg2rad",		1, 1, f_deg2rad},
+#endif
     {"delete",		1, 1, f_delete},
     {"did_filetype",	0, 0, f_did_filetype},
     {"diff_filler",	1, 1, f_diff_filler},
@@ -7434,6 +7508,9 @@
     {"eventhandler",	0, 0, f_eventhandler},
     {"executable",	1, 1, f_executable},
     {"exists",		1, 1, f_exists},
+#ifdef FEAT_FLOAT
+    {"exp",		1, 1, f_exp},
+#endif
     {"expand",		1, 2, f_expand},
     {"extend",		2, 3, f_extend},
     {"feedkeys",	1, 2, f_feedkeys},
@@ -7523,6 +7600,7 @@
     {"lispindent",	1, 1, f_lispindent},
     {"localtime",	0, 0, f_localtime},
 #ifdef FEAT_FLOAT
+    {"log",		1, 1, f_log},
     {"log10",		1, 1, f_log10},
 #endif
     {"map",		2, 2, f_map},
@@ -7550,6 +7628,9 @@
     {"prevnonblank",	1, 1, f_prevnonblank},
     {"printf",		2, 19, f_printf},
     {"pumvisible",	0, 0, f_pumvisible},
+#ifdef FEAT_FLOAT
+    {"rad2deg",		1, 1, f_rad2deg},
+#endif
     {"range",		1, 3, f_range},
     {"readfile",	1, 3, f_readfile},
     {"reltime",		0, 2, f_reltime},
@@ -7587,6 +7668,10 @@
     {"setwinvar",	3, 3, f_setwinvar},
     {"shellescape",	1, 1, f_shellescape},
     {"simplify",	1, 1, f_simplify},
+#ifdef FEAT_FLOAT
+    {"sin",		1, 1, f_sin},
+    {"sinh",		1, 1, f_sinh},
+#endif
     {"sort",		1, 2, f_sort},
     {"soundfold",	1, 1, f_soundfold},
     {"spellbadword",	0, 1, f_spellbadword},
@@ -7618,6 +7703,10 @@
     {"tabpagewinnr",	1, 2, f_tabpagewinnr},
     {"tagfiles",	0, 0, f_tagfiles},
     {"taglist",		1, 1, f_taglist},
+#ifdef FEAT_FLOAT
+    {"tan",		1, 1, f_tan},
+    {"tanh",		1, 1, f_tanh},
+#endif
     {"tempname",	0, 0, f_tempname},
     {"test",		1, 1, f_test},
     {"tolower",		1, 1, f_tolower},
@@ -8070,6 +8159,82 @@
  */
 
 /*
+ * "abs()" function
+ */
+    static void
+f_abs(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    varnumber_T n;
+#ifdef FEAT_FLOAT
+    float_T	f;
+
+    if (argvars[0].v_type == VAR_FLOAT)
+    {
+	rettv->v_type = VAR_FLOAT;
+	f = (float_T)argvars[0].vval.v_float;
+	rettv->vval.v_float = f>=0.0 ? f : -f;
+	return;
+    }
+#endif
+    rettv->v_type = VAR_NUMBER;
+    if (argvars[0].v_type == VAR_NUMBER)
+    {
+	n = (varnumber_T)argvars[0].vval.v_number;
+	rettv->vval.v_number = n>=0 ? n : -n;
+	return;
+    }
+    EMSG(_("E808: Number or Float required"));
+    rettv->vval.v_number = 0;
+
+}
+
+#ifdef FEAT_FLOAT
+static int get_float_arg __ARGS((typval_T *argvars, float_T *f));
+
+/*
+ * Get the float value of "argvars[0]" into "f".
+ * Returns FAIL when the argument is not a Number or Float.
+ */
+    static int
+get_float_arg(argvars, f)
+    typval_T	*argvars;
+    float_T	*f;
+{
+    if (argvars[0].v_type == VAR_FLOAT)
+    {
+	*f = argvars[0].vval.v_float;
+	return OK;
+    }
+    if (argvars[0].v_type == VAR_NUMBER)
+    {
+	*f = (float_T)argvars[0].vval.v_number;
+	return OK;
+    }
+    EMSG(_("E808: Number or Float required"));
+    return FAIL;
+}
+
+/*
+ * "acos()" function
+ */
+    static void
+f_acos(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    float_T	f;
+
+    rettv->v_type = VAR_FLOAT;
+    if (get_float_arg(argvars, &f) == OK)
+	rettv->vval.v_float = acos(f);
+    else
+	rettv->vval.v_float = 0.0;
+}
+#endif
+
+/*
  * "add(list, item)" function
  */
     static void
@@ -8196,6 +8361,60 @@
 	    list_append_string(rettv->vval.v_list,
 					       alist_name(&ARGLIST[idx]), -1);
 }
+
+#ifdef FEAT_FLOAT
+/*
+ * "asin()" function
+ */
+    static void
+f_asin(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    float_T	f;
+
+    rettv->v_type = VAR_FLOAT;
+    if (get_float_arg(argvars, &f) == OK)
+	rettv->vval.v_float = asin(f);
+    else
+	rettv->vval.v_float = 0.0;
+}
+
+/*
+ * "atan()" function
+ */
+    static void
+f_atan(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    float_T	f;
+
+    rettv->v_type = VAR_FLOAT;
+    if (get_float_arg(argvars, &f) == OK)
+	rettv->vval.v_float = atan(f);
+    else
+	rettv->vval.v_float = 0.0;
+}
+
+/*
+ * "atan2()" function
+ */
+    static void
+f_atan2(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    float_T	fx, fy;
+
+    rettv->v_type = VAR_FLOAT;
+    if (get_float_arg(argvars, &fx) == OK
+				     && get_float_arg(&argvars[1], &fy) == OK)
+	rettv->vval.v_float = atan2(fx, fy);
+    else
+	rettv->vval.v_float = 0.0;
+}
+#endif
 
 /*
  * "browse(save, title, initdir, default)" function
@@ -8584,31 +8803,6 @@
 	clear_tv(&argv[--argc]);
 }
 
-static int get_float_arg __ARGS((typval_T *argvars, float_T *f));
-
-/*
- * Get the float value of "argvars[0]" into "f".
- * Returns FAIL when the argument is not a Number or Float.
- */
-    static int
-get_float_arg(argvars, f)
-    typval_T	*argvars;
-    float_T	*f;
-{
-    if (argvars[0].v_type == VAR_FLOAT)
-    {
-	*f = argvars[0].vval.v_float;
-	return OK;
-    }
-    if (argvars[0].v_type == VAR_NUMBER)
-    {
-	*f = (float_T)argvars[0].vval.v_number;
-	return OK;
-    }
-    EMSG(_("E808: Number or Float required"));
-    return FAIL;
-}
-
 #ifdef FEAT_FLOAT
 /*
  * "ceil({float})" function
@@ -8887,6 +9081,42 @@
 {
     item_copy(&argvars[0], rettv, FALSE, 0);
 }
+
+#ifdef FEAT_FLOAT
+/*
+ * "cos()" function
+ */
+    static void
+f_cos(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    float_T	f;
+
+    rettv->v_type = VAR_FLOAT;
+    if (get_float_arg(argvars, &f) == OK)
+	rettv->vval.v_float = cos(f);
+    else
+	rettv->vval.v_float = 0.0;
+}
+
+/*
+ * "cosh()" function
+ */
+    static void
+f_cosh(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    float_T	f;
+
+    rettv->v_type = VAR_FLOAT;
+    if (get_float_arg(argvars, &f) == OK)
+	rettv->vval.v_float = cosh(f);
+    else
+	rettv->vval.v_float = 0.0;
+}
+#endif
 
 /*
  * "count()" function
@@ -9077,6 +9307,25 @@
     else
 	item_copy(&argvars[0], rettv, TRUE, noref == 0 ? ++current_copyID : 0);
 }
+
+#ifdef FEAT_FLOAT
+/*
+ * "deg2rad()" function
+ */
+    static void
+f_deg2rad(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    float_T	f;
+
+    rettv->v_type = VAR_FLOAT;
+    if (get_float_arg(argvars, &f) == OK)
+	rettv->vval.v_float = f * 3.141592653589793 / 180.0;
+    else
+	rettv->vval.v_float = 0.0;
+}
+#endif
 
 /*
  * "delete()" function
@@ -9366,6 +9615,25 @@
 
     rettv->vval.v_number = n;
 }
+
+#ifdef FEAT_FLOAT
+/*
+ * "exp()" function
+ */
+    static void
+f_exp(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    float_T	f;
+
+    rettv->v_type = VAR_FLOAT;
+    if (get_float_arg(argvars, &f) == OK)
+	rettv->vval.v_float = exp(f);
+    else
+	rettv->vval.v_float = 0.0;
+}
+#endif
 
 /*
  * "expand()" function
@@ -12827,6 +13095,23 @@
 
 #ifdef FEAT_FLOAT
 /*
+ * "log()" function
+ */
+    static void
+f_log(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    float_T	f;
+
+    rettv->v_type = VAR_FLOAT;
+    if (get_float_arg(argvars, &f) == OK)
+	rettv->vval.v_float = log(f);
+    else
+	rettv->vval.v_float = 0.0;
+}
+
+/*
  * "log10()" function
  */
     static void
@@ -13939,6 +14224,25 @@
 	    set_var(idvar, &v.di_tv, FALSE);
 	vim_free(v.di_tv.vval.v_string);
     }
+}
+#endif
+
+#ifdef FEAT_FLOAT
+/*
+ * "rad2deg()" function
+ */
+    static void
+f_rad2deg(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    float_T	f;
+
+    rettv->v_type = VAR_FLOAT;
+    if (get_float_arg(argvars, &f) == OK)
+	rettv->vval.v_float = f * 180 / 3.141592653589793;
+    else
+	rettv->vval.v_float = 0.0;
 }
 #endif
 
@@ -15639,6 +15943,42 @@
     rettv->v_type = VAR_STRING;
 }
 
+#ifdef FEAT_FLOAT
+/*
+ * "sin()" function
+ */
+    static void
+f_sin(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    float_T	f;
+
+    rettv->v_type = VAR_FLOAT;
+    if (get_float_arg(argvars, &f) == OK)
+	rettv->vval.v_float = sin(f);
+    else
+	rettv->vval.v_float = 0.0;
+}
+
+/*
+ * "sinh()" function
+ */
+    static void
+f_sinh(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    float_T	f;
+
+    rettv->v_type = VAR_FLOAT;
+    if (get_float_arg(argvars, &f) == OK)
+	rettv->vval.v_float = sinh(f);
+    else
+	rettv->vval.v_float = 0.0;
+}
+#endif
+
 static int
 #ifdef __BORLANDC__
     _RTLENTRYF
@@ -16840,6 +17180,42 @@
     if (rettv_list_alloc(rettv) == OK)
 	(void)get_tags(rettv->vval.v_list, tag_pattern);
 }
+
+#ifdef FEAT_FLOAT
+/*
+ * "tan()" function
+ */
+    static void
+f_tan(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    float_T	f;
+
+    rettv->v_type = VAR_FLOAT;
+    if (get_float_arg(argvars, &f) == OK)
+	rettv->vval.v_float = tan(f);
+    else
+	rettv->vval.v_float = 0.0;
+}
+
+/*
+ * "tanh()" function
+ */
+    static void
+f_tanh(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    float_T	f;
+
+    rettv->v_type = VAR_FLOAT;
+    if (get_float_arg(argvars, &f) == OK)
+	rettv->vval.v_float = tanh(f);
+    else
+	rettv->vval.v_float = 0.0;
+}
+#endif
 
 /*
  * "tempname()" function
diff -r 41941dee5dd7 src/vim.h
--- a/src/vim.h	Sat Jun 21 02:54:51 2008 +1000
+++ b/src/vim.h	Sat Jun 21 20:38:02 2008 +1000
@@ -1709,7 +1709,11 @@
 #define VV_MOUSE_LNUM   50
 #define VV_MOUSE_COL	51
 #define VV_OP		52
-#define VV_LEN		53	/* number of v: vars */
+#define VV_INF		53
+#define VV_NAN		54
+#define VV_E		55
+#define VV_PI		56
+#define VV_LEN		57	/* number of v: vars */
 
 #ifdef FEAT_CLIPBOARD
 
diff -r -u a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt
--- a/runtime/doc/usr_41.txt	2008-06-21 19:39:03.000000000 +1000
+++ b/runtime/doc/usr_41.txt	2008-06-21 20:35:18.000000000 +1000
@@ -580,7 +580,7 @@
 	nr2char()		get a character by its ASCII value
 	char2nr()		get ASCII value of a character
 	str2nr()		convert a string to a Number
-	str2float()		convert a string to a Float
+	str2float()		convert a string (or Number) to a Float
 	printf()		format a string according to % items
 	escape()		escape characters in a string with a '\'
 	shellescape()		escape a string for use with a shell command
@@ -650,13 +650,28 @@
 	count()			count number of times a value appears
 
 Floating point computation:
+	acos()			arc-cosine
+	asin()			arc-sine
+	atan()			arc-tangent
+	atan2()			arc-tangent
 	ceil()			round up
+	cos()			cosine
+	cosh()			hyperbolic cosine
+	deg2rad()		convert degrees to radians
+	exp()			natural exponential
 	float2nr()		convert Float to Number
 	floor()			round down
+	log()			natural logarithm
 	log10()			logarithm to base 10
 	pow()			value of x to the exponent y
+	rad2deg()		convert radians to degrees
 	round()			round off
+	sin()			sine
+	sinh()			hyperbolic sine
 	sqrt()			square root
+	str2float()		convert a string (or Number) to a Float
+	tan()			tangent
+	tanh()			hyperbolic tangent
 	trunc()			remove value after decimal point
 
 Variables:
diff -ur a/runtime/doc/eval.txt b/runtime/doc/eval.txt
--- a/runtime/doc/eval.txt	2008-06-21 21:00:05.000000000 +1000
+++ b/runtime/doc/eval.txt	2008-06-21 21:02:04.000000000 +1000
@@ -813,7 +813,9 @@
 Since '.' has lower precedence than '*'.  This does NOT work, since this
 attempts to concatenate a Float and a String.
 
-When the righthand side of '/' is zero, the result is 0x7fffffff.
+When the righthand side of '/' is zero, the result is 0x7fffffff if the
+lefthand side is positive, -0x7fffffff if it is negative, or
+-0x7fffffff-1 if it is zero.
 When the righthand side of '%' is zero, the result is 0.
 
 None of these work for |Funcref|s.
@@ -944,6 +946,8 @@
 {exp} is the exponent, power of 10.
 Only a decimal point is accepted, not a comma.  No matter what the current
 locale is.
+The built-in variables |v:inf|, |v:nan|, |v:e| and |v:pi|also provide useful
+floating point numbers.
 {only when compiled with the |+float| feature}
 
 Examples:
@@ -960,7 +964,13 @@
 	1e40		missing .{M}
 
 The precision and range of floating points numbers depends on the library Vim
-was compiled with.  There is no way to change this at runtime.
+was compiled with.  Ordinarily this will be double precision.  There is no way
+to change this at runtime.
+
+By default, however, only 6 decimal places are shown.  To show full precision,
+use printf() with %.15e.  Example: >
+	:echo printf('%.15e',atan(1))
+<	7.853981633974483e-01
 
 Rationale:
 Before floating point was introduced, the text "123.456" was interpreted as
@@ -1319,6 +1329,10 @@
 		Example: >
 	:au VimLeave * if v:dying | echo "\nAAAAaaaarrrggghhhh!!!\n" | endif
 <
+					*v:e*	    e-variable
+v:e		Euler's number (base of natural exponentials and logarithms).
+		2.718281828459045 with |+float| or 2 without.
+
 					*v:errmsg* *errmsg-variable*
 v:errmsg	Last given error message.  It's allowed to set this variable.
 		Example: >
@@ -1411,6 +1425,10 @@
 v:foldstart	Used for 'foldtext': first line of closed fold.
 		Read-only in the |sandbox|. |fold-foldtext|
 
+					*v:inf*	    inf-variable
+v:inf		Special floating point value Inf (infinity) with |+float|
+		or 0x7fffffff without.
+
 					*v:insertmode* *insertmode-variable*
 v:insertmode	Used for the |InsertEnter| and |InsertChange| autocommand
 		events.  Values:
@@ -1462,6 +1480,10 @@
 		This is the screen column number, like with |virtcol()|.  The
 		value is zero when there was no mouse button click.
 
+					*v:nan*	    nan-variable
+v:nan		Special floating point value NaN (not a number) with |+float|
+		or -0x7fffffff-1 without.
+
 					*v:operator* *operator-variable*
 v:operator	The last operator given in Normal mode.  This is a single
 		character except for commands starting with <g> or <z>,
@@ -1475,6 +1497,10 @@
 		commands.
 		Read-only.
 
+					*v:pi*	    pi-variable
+v:pi		Pi (ratio of circle's circumference to diameter).
+		3.141592653589793 with |+float| or 3 without.
+
 					*v:prevcount* *prevcount-variable*
 v:prevcount	The count given for the last but one Normal mode command.
 		This is the v:count value of the previous command.  Useful if
@@ -1609,6 +1635,8 @@
 
 USAGE				RESULT	DESCRIPTION	~
 
+abs( {expr})			Number/Float absolute value of {expr}
+acos( {expr})			Float	arc-cosine of {expr}
 add( {list}, {item})		List	append {item} to |List| {list}
 append( {lnum}, {string})	Number	append {string} below line {lnum}
 append( {lnum}, {list})		Number	append lines {list} below line {lnum}
@@ -1616,6 +1644,9 @@
 argidx()			Number	current index in the argument list
 argv( {nr})			String	{nr} entry of the argument list
 argv( )				List	the argument list
+asin( {expr})			Float	arc-sine of {expr}
+atan( {expr})			Float	arc-tangent of {expr}
+atan2( {y}, {x})		Float	arc-tangent of {y}/{x}
 browse( {save}, {title}, {initdir}, {default})
 				String	put up a file requester
 browsedir( {title}, {initdir})  String	put up a directory requester
@@ -1635,6 +1666,8 @@
 cindent( {lnum})		Number	C indent for line {lnum}
 clearmatches()			None	clear all matches
 col( {expr})			Number	column nr of cursor or mark
+cos( {expr})			Float	cosine of {expr}
+cosh( {expr})			Float	hyperbolic cosine of {expr}
 complete({startcol}, {matches})	String  set Insert mode completion
 complete_add( {expr})		Number	add completion match
 complete_check()		Number  check for key typed during completion
@@ -1649,6 +1682,7 @@
 				Number	move cursor to {lnum}, {col}, {coladd}
 cursor( {list})			Number	move cursor to position in {list}
 deepcopy( {expr})		any	make a full copy of {expr}
+deg2rad( {expr})		Float	convert {expr} from degrees to radians
 delete( {fname})		Number	delete file {fname}
 did_filetype()			Number	TRUE if FileType autocommand event used
 diff_filler( {lnum})		Number	diff filler lines about {lnum}
@@ -1659,9 +1693,10 @@
 eventhandler( )			Number	TRUE if inside an event handler
 executable( {expr})		Number	1 if executable {expr} exists
 exists( {expr})			Number	TRUE if {expr} exists
+exp( {expr})			Float	natural exponential of {expr}
+expand( {expr})			String	expand special keywords in {expr}
 extend({expr1}, {expr2} [, {expr3}])
 				List/Dict insert items of {expr2} into {expr1}
-expand( {expr})			String	expand special keywords in {expr}
 feedkeys( {string} [, {mode}])	Number  add key sequence to typeahead buffer
 filereadable( {file})		Number	TRUE if {file} is a readable file
 filewritable( {file})		Number	TRUE if {file} is a writable file
@@ -1751,6 +1786,7 @@
 line2byte( {lnum})		Number	byte count of line {lnum}
 lispindent( {lnum})		Number	Lisp indent for line {lnum}
 localtime()			Number	current time
+log( {expr})			Float	natural logarithm of Float {expr}
 log10( {expr})			Float	logarithm of Float {expr} to base 10
 map( {expr}, {string})		List/Dict  change each item in {expr} to {expr}
 maparg( {name}[, {mode} [, {abbr}]])
@@ -1781,6 +1817,7 @@
 prevnonblank( {lnum})		Number	line nr of non-blank line <= {lnum}
 printf( {fmt}, {expr1}...)	String  format text
 pumvisible()			Number  whether popup menu is visible
+rad2deg( {expr})		Float	convert {expr} from radians to degrees
 range( {expr} [, {max} [, {stride}]])
 				List	items from {expr} to {max}
 readfile({fname} [, {binary} [, {max}]])
@@ -1830,6 +1867,8 @@
 shellescape( {string})		String	escape {string} for use as shell
 					command argument
 simplify( {filename})		String	simplify filename as much as possible
+sin( {expr})			Float	sine of {expr}
+sinh( {expr})			Float	hyperbolic sine of {expr}
 sort( {list} [, {func}])	List	sort {list}, using {func} to compare
 soundfold( {word})		String	sound-fold {word}
 spellbadword()			String	badly spelled word at cursor
@@ -1864,6 +1903,8 @@
 				Number	number of current window in tab page
 taglist( {expr})		List	list of tags matching {expr}
 tagfiles()			List    tags files used
+tan( {expr})			Float	tangent of {expr}
+tanh( {expr})			Float	hyperbolic tangent of {expr}
 tempname()			String	name for a temporary file
 tolower( {expr})		String	the String {expr} switched to lowercase
 toupper( {expr})		String	the String {expr} switched to uppercase
@@ -1886,6 +1927,27 @@
 writefile({list}, {fname} [, {binary}])
 				Number	write list of lines to file {fname}
 
+abs({expr})						*abs()*
+		Return the absolute value of {expr}.
+		{expr} must evaluate to a |Float| or a |Number|.
+		Example: >
+			:echo abs(-12)
+<			12 >
+			:echo abs(-34.56)
+<			34.56 >
+			:echo abs(78.9)
+<			78.9
+
+acos({expr})						*acos()*
+		Return the principal value of the arc-cosine of Float {expr}
+		in radians as a |Float|. It will be in the range [0,pi].
+		If you want degrees, use |rad2deg()|.
+		{expr} must evaluate to a |Float| or a |Number|.
+		Example: >
+			:echo acos(-1)
+<			3.141593
+		{only available when compiled with the |+float| feature}
+
 add({list}, {expr})					*add()*
 		Append the item {expr} to |List| {list}.  Returns the
 		resulting |List|.  Examples: >
@@ -1928,6 +1990,37 @@
 <		Without the {nr} argument a |List| with the whole |arglist| is
 		returned.
 
+asin({expr})						*asin()*
+		Return the principal value of the arc-cosine of Float {expr}
+		in radians as a |Float|. It will be in the range [-pi/2,pi/2].
+		If you want degrees, use |rad2deg()|.
+		{expr} must evaluate to a |Float| or a |Number|.
+		Example: >
+			:echo asin(-1)
+<			-1.570796
+		{only available when compiled with the |+float| feature}
+
+atan({expr})						*atan()*
+		Return the principal value of the arc-tangent of Float {expr}
+		in radians as a |Float|. It will be in the range [-pi/2,pi/2].
+		If you want degrees, use |rad2deg()|.
+		{expr} must evaluate to a |Float| or a |Number|.
+		Example: >
+			:echo asin(v:inf)
+<			1.570796
+		{only available when compiled with the |+float| feature}
+
+atan2({y},{x})						*atan2()*
+		Return the arc-tangent of {y}/{x}, using the signs of {y} and
+		{x} to determine the quadrant, in radians as a |Float|.
+		It will be in the range (-pi,pi].
+		If you want degrees, use |rad2deg()|.
+		{y} and {x} each must evaluate to a |Float| or a |Number|.
+		Example: >
+			:echo atan2(0,-1)
+<			3.141593
+		{only available when compiled with the |+float| feature}
+
 							*browse()*
 browse({save}, {title}, {initdir}, {default})
 		Put up a file requester.  This only works when "has("browse")"
@@ -2262,6 +2355,24 @@
 		changing an item changes the contents of both |Lists|.  Also
 		see |deepcopy()|.
 
+cos({expr})						*cos()*
+		Return the cosine of Float {expr} (an angle measured in
+		radians) as a |Float|.
+		If you want to provide degrees, use |deg2rad()|.
+		{expr} must evaluate to a |Float| or a |Number|.
+		Example: >
+			:echo cos(v:pi)
+<			-1.0
+		{only available when compiled with the |+float| feature}
+
+cosh({expr})						*cosh()*
+		Return the hyperbolic cosine of Float {expr} as a |Float|.
+		{expr} must evaluate to a |Float| or a |Number|.
+		Example: >
+			:echo cosh(0)
+<			1.0
+		{only available when compiled with the |+float| feature}
+
 count({comp}, {expr} [, {ic} [, {start}]])			*count()*
 		Return the number of times an item with value {expr} appears
 		in |List| or |Dictionary| {comp}.
@@ -2350,6 +2461,19 @@
 		{noref} set to 1 will fail.
 		Also see |copy()|.
 
+deg2rad({expr})						*deg2rad()*
+		Return the Float {expr} converted from degrees to radians as a
+		|Float|.
+		The same as doing {expr}*180/v:pi except you don't have to
+		remember the formula.
+		{expr} must evaluate to a |Float| or a |Number|.
+		Examples: >
+			:echo deg2rad(90)
+<			1.570796 >
+			:echo sin(deg2rad(90))
+<			1.0
+		{only available when compiled with the |+float| feature}
+
 delete({fname})							*delete()*
 		Deletes the file by the name {fname}.  The result is a Number,
 		which is 0 if the file was deleted successfully, and non-zero
@@ -2514,6 +2638,19 @@
 <		This doesn't check for existence of the "bufcount" variable,
 		but gets the value of "bufcount", and checks if that exists.
 
+exp({expr})						*exp()*
+		Return the natural exponential of Float {expr} (base e raised
+		to the power of {expr}) as a |Float|.
+		{expr} must evaluate to a |Float| or a |Number|.
+		Examples: >
+			:echo exp(1)
+<			2.718282 >
+			:echo exp(0.5)
+<			1.648721 >
+			:echo exp(-1)
+<			0.367879
+		{only available when compiled with the |+float| feature}
+
 expand({expr} [, {flag}])				*expand()*
 		Expand wildcards and the following special keywords in {expr}.
 		The result is a String.
@@ -2710,10 +2847,12 @@
 
 float2nr({expr})					*float2nr()*
 		Convert {expr} to a Number by omitting the part after the
-		decimal point.
+		decimal point.  To get a different type of rounding, use
+		|floor()|, |ceil()| or |round()| first.
 		{expr} must evaluate to a |Float| or a Number.
 		When the value of {expr} is out of range for a |Number| the
 		result is truncated to 0x7fffffff or -0x7fffffff.
+		When the value of {expr} is NaN the result is -0x7fffffff-1.
 		Examples: >
 			echo float2nr(3.95)
 <			3  >
@@ -2723,11 +2862,12 @@
 <			2147483647  >
 			echo float2nr(-1.0e150)
 <			-2147483647  >
+			echo float2nr(v:nan)
+<			-2147483648  >
 			echo float2nr(1.0e-100)
 <			0
 		{only available when compiled with the |+float| feature}
 
-
 floor({expr})							*floor()*
 		Return the largest integral value less than or equal to
 		{expr} as a |Float| (round down).
@@ -3677,6 +3817,16 @@
 		Return the current time, measured as seconds since 1st Jan
 		1970.  See also |strftime()| and |getftime()|.
 
+log({expr})						*log()*
+		Return the natural logarithm of Float {expr} (to base e)
+		as a |Float|.
+		{expr} must evaluate to a |Float| or a |Number|.
+		Examples: >
+			:echo log(v:e)
+<			1.0 >
+			:echo log(2)
+<			0.693147
+		{only available when compiled with the |+float| feature}
 
 log10({expr})						*log10()*
 		Return the logarithm of Float {expr} to base 10 as a |Float|.
@@ -3687,7 +3837,7 @@
 			:echo log10(0.01)
 <			-2.0
 		{only available when compiled with the |+float| feature}
-		
+
 map({expr}, {string})					*map()*
 		{expr} must be a |List| or a |Dictionary|.
 		Replace each item in {expr} with the result of evaluating
@@ -4022,7 +4172,9 @@
 			:echo pow(3, 3)
 <			27.0 >
 			:echo pow(2, 16)
-<			65536.0
+<			65536.0 >
+			:echo pow(32, 0.2)
+<			2.0
 		{only available when compiled with the |+float| feature}
 		
 prevnonblank({lnum})					*prevnonblank()*
@@ -4207,6 +4359,19 @@
 		This can be used to avoid some things that would remove the
 		popup menu.
 
+rad2deg({expr})						*rad2deg()*
+		Return the Float {expr} converted from radians to degrees as a
+		|Float|.
+		The same as doing {expr}*180/v:pi except you don't have to
+		remember the formula.
+		{expr} must evaluate to a |Float| or a |Number|.
+		Examples: >
+			:echo rad2deg(2*v:pi)
+<			360.0 >
+			:echo rad2deg(atan(1))
+<			45.0
+		{only available when compiled with the |+float| feature}
+
 							*E726* *E727*
 range({expr} [, {max} [, {stride}]])				*range()*
 		Returns a |List| with Numbers:
@@ -4886,6 +5051,24 @@
 		links before simplifying the path name, use |resolve()|.
 
 
+sin({expr})						*sin()*
+		Return the sine of Float {expr} (an angle measured in
+		radians) as a |Float|.
+		If you want to provide degrees, use |deg2rad()|.
+		{expr} must evaluate to a |Float| or a |Number|.
+		Example: >
+			:echo sin(v:pi)
+<			1.224606e-16
+		{only available when compiled with the |+float| feature}
+
+sinh({expr})						*sinh()*
+		Return the hyperbolic sine of Float {expr} as a |Float|.
+		{expr} must evaluate to a |Float| or a |Number|.
+		Example: >
+			:echo sinh(1)
+<			1.175201
+		{only available when compiled with the |+float| feature}
+
 sort({list} [, {func}])					*sort()* *E702*
 		Sort the items in {list} in-place.  Returns {list}.  If you
 		want a list to remain unmodified make a copy first: >
@@ -5008,7 +5191,6 @@
 		different base the result will be zero.
 		Text after the number is silently ignored.
 
-
 str2float( {expr})					*str2float()*
 		Convert string {expr} to a Float.  This mostly works the same
 		as when using a floating point number in an expression, see
@@ -5021,8 +5203,9 @@
 		12.0.  You can strip out thousands separators with
 		|substitute()|: >
 			let f = str2float(substitute(text, ',', '', 'g'))
-<		{only available when compiled with the |+float| feature}
-
+<		It also works to convert Numbers to floats because of
+		automatic Number to string conversion.
+		{only available when compiled with the |+float| feature}
 
 strftime({format} [, {time}])				*strftime()*
 		The result is a String, which is a formatted date and time, as
@@ -5342,6 +5525,24 @@
 		located by Vim. Refer to |tags-file-format| for the format of
 		the tags file generated by the different ctags tools.
 
+tan({expr})						*tan()*
+		Return the tangent of Float {expr} (an angle measured in
+		radians) as a |Float|.
+		If you want to provide degrees, use |deg2rad()|.
+		{expr} must evaluate to a |Float| or a |Number|.
+		Example: >
+			:echo tan(0)
+<			0.0
+		{only available when compiled with the |+float| feature}
+
+tanh({expr})						*tanh()*
+		Return the hyperbolic tangent of Float {expr} as a |Float|.
+		{expr} must evaluate to a |Float| or a |Number|.
+		Example: >
+			:echo tanh(1)
+<			0.761594
+		{only available when compiled with the |+float| feature}
+
 tempname()					*tempname()* *temp-file-name*
 		The result is a String, which is the name of a file that
 		doesn't exist.  It can be used for a temporary file.  The name

Raspunde prin e-mail lui