1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-01-19 11:31:26 +01:00

Initial revision

This commit is contained in:
Tanaka Akira 1999-09-22 13:33:14 +00:00
parent 3d74a2f689
commit e7384c33a4
4 changed files with 632 additions and 0 deletions

View file

@ -0,0 +1,95 @@
#autoload
# Usage:
# _combination [-s S] V[:K1:...] Ki1[:Ni1]=Pi1 Ki2[:Ni2]=Pi2 ... Kim[:Nim]=Pim Kj[:Nj] EXPL...
#
# It is assumed that V is formed as PRE_K1_..._Kn if `:K1:...' is not specified.
#
# Example: telnet
#
# Assume an user sets the variable `telnet_hosts_ports_users' as:
#
# telnet_hosts_ports_users=(
# host0:: host1::user1 host2::user2
# mail-server:{smtp,pop3}:
# news-server:nntp:
# proxy-server:8000:
# )
#
# `_telnet completes' hosts as:
#
# _combination telnet_hosts_ports_users \
# ${options[-l]:+users=${options[-l]:q}} \
# hosts "$expl[@]"
#
# This completes `host1', `host2', `mail-server', `news-server' and
# `proxy-server' according to the user given with `-l' if it is exists.
# And if it is failed, `_hosts' is called.
#
# `_telnet' completes ports as:
#
# _combination telnet_hosts_ports_users \
# ${options[-l]:+users=${options[-l]:q}} \
# hosts="${line[2]:q}" \
# ports "$expl[@]"
#
# This completes `smtp', `pop3', `nntp' and `8000' according to the
# host argument --- $line[2] and the user option argument if it is
# exists. And if it is failed, `_ports' is called.
#
# `_telnet' completes users for an argument of option `-l' as:
#
# _combination telnet_hosts_ports_users \
# ${line[2]:+hosts="${line[2]:q}"} \
# ${line[3]:+ports="${line[3]:q}"} \
# users "$expl[@]"
#
# This completes `user1' and `user2' according to the host argument and
# the port argument if they are exist. And if it is failed, `_users' is
# called.
local sep var keys pats key num tmp
if [[ "$1" = -s ]]; then
sep="$2"
shift 2
else
sep=:
fi
var=$1
shift
if [[ $var = *:* ]]; then
keys=( ${(s/:/)var} )
shift keys
var="${var%%:*}"
else
keys=( "${(@s:_:)${var#*_}}" )
fi
pats=( "${(@)keys/*/*}" )
while [[ "$1" = *=* ]]; do
tmp="${1%%\=*}"
key="${tmp%:*}"
num="${${tmp##*:}:-1}"
pats[$keys[(in:num:)$key]]="${1#*\=}"
shift
done
key="${1%:*}"
num="${${1##*:}:-1}"
shift
if (( ${(P)+${var}} )); then
eval "tmp=( \"\${(@M)${var}:#\${(j($sep))~pats}}\" )"
if (( keys[(in:num:)$key] != 1 )); then
eval "tmp=( \${tmp#\${(j(${sep}))~\${(@)\${(@)keys[2,(rn:num:)\$key]}/*/*}}$sep} )"
fi
tmp=( ${tmp%%$sep*} )
compadd "$@" - $tmp || { builtin functions _$key >&- && _$key "$@" }
else
builtin functions _$key >&- && _$key "$@"
fi

52
Doc/Zsh/mod_mathfunc.yo Normal file
View file

@ -0,0 +1,52 @@
texinode(The mathfunc Module)(The parameter Module)(The mapfile Module)(Zsh Modules)
sect(The mathfunc Module)
cindex(functions, mathematical)
cindex(mathematical functions)
The tt(mathfunc) module provides standard mathematical functions for use when
evaluating mathematical formulae. The syntax agrees with normal C and
FORTRAN conventions, for example,
example((( f = sin(0.3) )))
assigns the sine of 0.3 to the parameter f.
Most functions take floating point arguments and return a floating point
value. However, any necessary conversions from or to integer type will be
performed automatically by the shell. Apart from tt(atan) with a second
argument and the tt(abs), tt(int) and tt(float) functions, all functions
behave as noted in the manual page for the corresponding C function,
except that any arguments out of range for the function in question will be
detected by the shell and an error reported.
The following functions take a single floating point argument: tt(acos),
tt(acosh), tt(asin), tt(asinh), tt(atan), tt(atanh), tt(cbrt), tt(ceil),
tt(cos), tt(cosh), tt(erf), tt(erfc), tt(exp), tt(expm1), tt(fabs),
tt(floor), tt(gamma), tt(j0), tt(j1), tt(lgamma), tt(log), tt(log10),
tt(log1p), tt(logb), tt(sin), tt(sinh), tt(sqrt), tt(tan), tt(tanh),
tt(y0), tt(y1). The tt(atan) function can optionally take a second
argument, in which case it behaves like the C function tt(atan2).
The tt(ilogb) function takes a single floating point argument, but
returns an integer.
The function tt(signgam) takes no arguments, and returns an integer, which
is the C variable of the same name, as described in manref(gamma)(3). Note
that it is therefore only useful immediately after a call to tt(gamma) or
tt(lgamma). Note also that `tt(signgam())' and `tt(signgam)' are distinct
expresssions.
The following functions take two floating point arguments: tt(copysign),
tt(drem), tt(fmod), tt(hypot), tt(nextafter).
The following take an integer first argument and a floating point second
argument: tt(jn), tt(yn).
The following take a floating point first argument and an integer second
argument: tt(ldexp), tt(scalb).
The function tt(abs) does not convert the type of its single argument; it
returns the absolute value of either a floating point number or an
integer. The functions tt(float) and tt(int) convert their arguments into
a floating point or integer value (by truncation) respectively.
Note that the C tt(pow) function is available in ordinary math evaluation
as the `tt(**)' operator and is not provided here.

482
Src/Modules/mathfunc.c Normal file
View file

@ -0,0 +1,482 @@
/*
* mathfunc.c - basic mathematical functions for use in math evaluations
*
* This file is part of zsh, the Z shell.
*
* Copyright (c) 1999 Peter Stephenson
* All rights reserved.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and to distribute modified versions of this software for any
* purpose, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* In no event shall Peter Stephenson or the Zsh Development Group be liable
* to any party for direct, indirect, special, incidental, or consequential
* damages arising out of the use of this software and its documentation,
* even if Peter Stephenson and the Zsh Development Group have been advised of
* the possibility of such damage.
*
* Peter Stephenson and the Zsh Development Group specifically disclaim any
* warranties, including, but not limited to, the implied warranties of
* merchantability and fitness for a particular purpose. The software
* provided hereunder is on an "as is" basis, and Peter Stephenson and the
* Zsh Development Group have no obligation to provide maintenance,
* support, updates, enhancements, or modifications.
*
*/
#include "mathfunc.mdh"
#include "mathfunc.pro"
#include <math.h>
enum {
MF_ABS,
MF_ACOS,
MF_ACOSH,
MF_ASIN,
MF_ASINH,
MF_ATAN,
MF_ATANH,
MF_CBRT,
MF_CEIL,
MF_COPYSIGN,
MF_COS,
MF_COSH,
MF_DREM,
MF_ERF,
MF_ERFC,
MF_EXP,
MF_EXPM1,
MF_FABS,
MF_FLOAT,
MF_FLOOR,
MF_FMOD,
MF_GAMMA,
MF_HYPOT,
MF_ILOGB,
MF_INT,
MF_J0,
MF_J1,
MF_JN,
MF_LDEXP,
MF_LGAMMA,
MF_LOG,
MF_LOG10,
MF_LOG1P,
MF_LOGB,
MF_NEXTAFTER,
MF_RINT,
MF_SCALB,
MF_SIGNGAM,
MF_SIN,
MF_SINH,
MF_SQRT,
MF_TAN,
MF_TANH,
MF_Y0,
MF_Y1,
MF_YN,
};
/*
* also to do, but differently argument or returned: abs (no type
* conversion), atan2.
*/
/* Flags for bounds. Note these must start at 1, not 0. */
enum {
BF_POS = 1, /* must be positive */
BF_NONNEG = 2, /* must be non-negative */
BF_FRAC = 3, /* must be -1 <= x <= 1 */
BF_GE1 = 4, /* must be >= 1 */
BF_FRACO = 5, /* must be in open range -1 < x < 1 */
BF_INTPOS = 6, /* must be non-integer or positive */
BF_GTRM1 = 7, /* must be > -1 */
BF_NONZ = 8, /* must be nonzero */
BF_POS2 = 9 /* second argument must be positive */
};
#define BFLAG(x) ((x) << 8)
/*
* Flags for type of function: unlike the above, these must
* be individually bit-testable.
*/
enum {
TF_NOCONV = 1, /* don't convert to float */
TF_INT1 = 2, /* first argument is integer */
TF_INT2 = 4, /* second argument is integer */
TF_NOASS = 8 /* don't assign result as double */
};
#define TFLAG(x) ((x) << 16)
static struct mathfunc mftab[] = {
NUMMATHFUNC("abs", math_func, 1, 1, MF_ABS | BFLAG(BF_FRAC) |
TFLAG(TF_NOCONV|TF_NOASS)),
NUMMATHFUNC("acos", math_func, 1, 1, MF_ACOS | BFLAG(BF_FRAC)),
NUMMATHFUNC("acosh", math_func, 1, 1, MF_ACOSH | BFLAG(BF_GE1)),
NUMMATHFUNC("asin", math_func, 1, 1, MF_ASIN | BFLAG(BF_FRAC)),
NUMMATHFUNC("asinh", math_func, 1, 1, MF_ASINH),
NUMMATHFUNC("atan", math_func, 1, 2, MF_ATAN),
NUMMATHFUNC("atanh", math_func, 1, 1, MF_ATANH | BFLAG(BF_FRACO)),
NUMMATHFUNC("cbrt", math_func, 1, 1, MF_CBRT),
NUMMATHFUNC("ceil", math_func, 1, 1, MF_CEIL),
NUMMATHFUNC("copysign", math_func, 2, 2, MF_COPYSIGN),
NUMMATHFUNC("cos", math_func, 1, 1, MF_COS),
NUMMATHFUNC("cosh", math_func, 1, 1, MF_COSH),
NUMMATHFUNC("drem", math_func, 2, 2, MF_DREM),
NUMMATHFUNC("erf", math_func, 1, 1, MF_ERF),
NUMMATHFUNC("erfc", math_func, 1, 1, MF_ERFC),
NUMMATHFUNC("exp", math_func, 1, 1, MF_EXP),
NUMMATHFUNC("expm1", math_func, 1, 1, MF_EXPM1),
NUMMATHFUNC("fabs", math_func, 1, 1, MF_FABS),
NUMMATHFUNC("float", math_func, 1, 1, MF_FLOAT),
NUMMATHFUNC("floor", math_func, 1, 1, MF_FLOOR),
NUMMATHFUNC("fmod", math_func, 2, 2, MF_FMOD),
NUMMATHFUNC("gamma", math_func, 1, 1, MF_GAMMA | BFLAG(BF_INTPOS)),
NUMMATHFUNC("hypot", math_func, 2, 2, MF_HYPOT),
NUMMATHFUNC("ilogb", math_func, 1, 1, MF_ILOGB | BFLAG(BF_NONZ) |
TFLAG(TF_NOASS)),
NUMMATHFUNC("int", math_func, 1, 1, MF_INT | TFLAG(TF_NOASS)),
NUMMATHFUNC("j0", math_func, 1, 1, MF_J0),
NUMMATHFUNC("j1", math_func, 1, 1, MF_J1),
NUMMATHFUNC("jn", math_func, 2, 2, MF_JN | TFLAG(TF_INT1)),
NUMMATHFUNC("ldexp", math_func, 2, 2, MF_LDEXP | TFLAG(TF_INT2)),
NUMMATHFUNC("lgamma", math_func, 1, 1, MF_LGAMMA | BFLAG(BF_INTPOS)),
NUMMATHFUNC("log", math_func, 1, 1, MF_LOG | BFLAG(BF_POS)),
NUMMATHFUNC("log10", math_func, 1, 1, MF_LOG10 | BFLAG(BF_POS)),
NUMMATHFUNC("log1p", math_func, 1, 1, MF_LOG1P | BFLAG(BF_GTRM1)),
NUMMATHFUNC("logb", math_func, 1, 1, MF_LOGB | BFLAG(BF_NONZ)),
NUMMATHFUNC("nextafter", math_func, 2, 2, MF_NEXTAFTER),
NUMMATHFUNC("rint", math_func, 1, 1, MF_RINT),
NUMMATHFUNC("scalb", math_func, 2, 2, MF_SCALB | TFLAG(TF_INT2)),
NUMMATHFUNC("signgam", math_func, 0, 0, MF_SIGNGAM | TFLAG(TF_NOASS)),
NUMMATHFUNC("sin", math_func, 1, 1, MF_SIN),
NUMMATHFUNC("sinh", math_func, 1, 1, MF_SINH),
NUMMATHFUNC("sqrt", math_func, 1, 1, MF_SQRT | BFLAG(BF_NONNEG)),
NUMMATHFUNC("tan", math_func, 1, 1, MF_TAN),
NUMMATHFUNC("tanh", math_func, 1, 1, MF_TANH),
NUMMATHFUNC("y0", math_func, 1, 1, MF_Y0 | BFLAG(BF_POS)),
NUMMATHFUNC("y1", math_func, 1, 1, MF_Y1 | BFLAG(BF_POS)),
NUMMATHFUNC("yn", math_func, 2, 2, MF_YN | BFLAG(BF_POS2) | TFLAG(TF_INT1))
};
/**/
static mnumber
math_func(char *name, int argc, mnumber *argv, int id)
{
mnumber ret;
double argd = 0, argd2 = 0, retd = 0;
int argi = 0;
if (argc && !(id & TFLAG(TF_NOCONV))) {
if (id & TFLAG(TF_INT1))
argi = (argv->type == MN_FLOAT) ? (zlong)argv->u.d : argv->u.l;
else
argd = (argv->type == MN_INTEGER) ? (double)argv->u.l : argv->u.d;
if (argc > 1) {
if (id & TFLAG(TF_INT2))
argi = (argv[1].type == MN_FLOAT) ? (zlong)argv[1].u.d :
argv[1].u.l;
else
argd2 = (argv[1].type == MN_INTEGER) ? (double)argv[1].u.l :
argv[1].u.d;
}
}
ret.type = MN_FLOAT;
ret.u.d = 0;
if (errflag)
return ret;
if (id & 0xff00) {
int rtst = 0;
switch ((id >> 8) & 0xff) {
case BF_POS:
rtst = (argd <= 0.0);
break;
case BF_NONNEG:
rtst = (argd < 0.0);
break;
case BF_FRAC:
rtst = (fabs(argd) > 1.0);
break;
case BF_GE1:
rtst = (argd < 1.0);
break;
case BF_FRACO:
rtst = (fabs(argd) >= 1.0);
break;
case BF_INTPOS:
rtst = (argd <= 0 && (double)(zlong)argd == argd);
break;
case BF_GTRM1:
rtst = (argd <= -1);
break;
case BF_POS2:
rtst = (argd2 <= 0.0);
break;
}
if (rtst) {
zerr("math: argument to %s out of range", name, 0);
return ret;
}
}
switch (id & 0xff) {
case MF_ABS:
ret.type = argv->type;
if (argv->type == MN_INTEGER)
ret.u.l = (argv->u.l < 0) ? - argv->u.l : argv->u.l;
else
ret.u.d = fabs(argv->u.d);
break;
case MF_ACOS:
retd = acos(argd);
break;
case MF_ACOSH:
retd = acosh(argd);
break;
case MF_ASIN:
retd = asin(argd);
break;
case MF_ASINH:
retd = asinh(argd);
break;
case MF_ATAN:
if (argc == 2)
retd = atan2(argd, argd2);
else
retd = atan(argd);
break;
case MF_ATANH:
retd = atanh(argd);
break;
case MF_CBRT:
retd = cbrt(argd);
break;
case MF_CEIL:
retd = ceil(argd);
break;
case MF_COPYSIGN:
retd = copysign(argd, argd2);
break;
case MF_COS:
retd = cos(argd);
break;
case MF_COSH:
retd = cosh(argd);
break;
case MF_DREM:
retd = drem(argd, argd2);
break;
case MF_ERF:
retd = erf(argd);
break;
case MF_ERFC:
retd = erfc(argd);
break;
case MF_EXP:
retd = exp(argd);
break;
case MF_EXPM1:
retd = expm1(argd);
break;
case MF_FABS:
retd = fabs(argd);
break;
case MF_FLOAT:
retd = argd;
break;
case MF_FLOOR:
retd = floor(argd);
break;
case MF_FMOD:
retd = fmod(argd, argd2);
break;
case MF_GAMMA:
retd = gamma(argd);
break;
case MF_HYPOT:
retd = hypot(argd, argd2);
break;
case MF_ILOGB:
ret.type = MN_INTEGER;
ret.u.l = ilogb(argd);
break;
case MF_INT:
ret.type = MN_INTEGER;
ret.u.l = (zlong)argd;
break;
case MF_J0:
retd = j0(argd);
break;
case MF_J1:
retd = j1(argd);
break;
case MF_JN:
retd = jn(argi, argd2);
break;
case MF_LDEXP:
retd = ldexp(argd, argi);
break;
case MF_LGAMMA:
retd = lgamma(argd);
break;
case MF_LOG:
retd = log(argd);
break;
case MF_LOG10:
retd = log10(argd);
break;
case MF_LOG1P:
retd = log1p(argd);
break;
case MF_LOGB:
retd = logb(argd);
break;
case MF_NEXTAFTER:
retd = nextafter(argd, argd2);
break;
case MF_RINT:
retd = rint(argd);
break;
case MF_SCALB:
retd = scalb(argd, argi);
break;
case MF_SIGNGAM:
ret.type = MN_INTEGER;
ret.u.l = signgam;
break;
case MF_SIN:
retd = sin(argd);
break;
case MF_SINH:
retd = sinh(argd);
break;
case MF_SQRT:
retd = sqrt(argd);
break;
case MF_TAN:
retd = tan(argd);
break;
case MF_TANH:
retd = tanh(argd);
break;
case MF_Y0:
retd = y0(argd);
break;
case MF_Y1:
retd = y1(argd);
break;
case MF_YN:
retd = yn(argi, argd2);
break;
#ifdef DEBUG
default:
fprintf(stderr, "BUG: mathfunc type not handled: %d", id);
break;
#endif
}
if (!(id & TFLAG(TF_NOASS)))
ret.u.d = retd;
return ret;
}
/**/
int
setup_mathfunc(Module m)
{
return 0;
}
/**/
int
boot_mathfunc(Module m)
{
return !addmathfuncs(m->nam, mftab, sizeof(mftab)/sizeof(*mftab));
}
#ifdef MODULE
/**/
int
cleanup_mathfunc(Module m)
{
deletemathfuncs(m->nam, mftab, sizeof(mftab)/sizeof(*mftab));
return 0;
}
/**/
int
finish_mathfunc(Module m)
{
return 0;
}
#endif

3
Src/Modules/mathfunc.mdd Normal file
View file

@ -0,0 +1,3 @@
autobins="mathfunc"
objects="mathfunc.o"