aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/func.c190
1 files changed, 166 insertions, 24 deletions
diff --git a/src/func.c b/src/func.c
index 09e44345d..7bfd5bd6a 100644
--- a/src/func.c
+++ b/src/func.c
@@ -1904,6 +1904,18 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
return 1;
}
+/* Mathematical Constants */
+#ifndef M_PI
+# define M_PI 3.141592653589793238462643383279502884
+#endif
+#ifndef M_LN10
+# define M_LN10 2.302585092994045684017991454684364208
+#endif
+#ifndef M_LN2
+# define M_LN2 0.693147180559945309417232121458176568
+#endif
+
+
/* Extra math functions that require linking with -lm
*/
#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
@@ -1923,17 +1935,19 @@ static void ceilingFunc(
sqlite3_value **argv
){
assert( argc==1 );
- switch( sqlite3_value_type(argv[0]) ){
- case SQLITE_INTEGER:
+ switch( sqlite3_value_numeric_type(argv[0]) ){
+ case SQLITE_INTEGER: {
sqlite3_result_int64(context, sqlite3_value_int64(argv[0]));
break;
- case SQLITE_NULL:
- break;
- default: {
+ }
+ case SQLITE_FLOAT: {
double (*x)(double) = (double(*)(double))sqlite3_user_data(context);
sqlite3_result_double(context, x(sqlite3_value_double(argv[0])));
break;
}
+ default: {
+ break;
+ }
}
}
@@ -1941,39 +1955,143 @@ static void ceilingFunc(
** Implementation of SQL functions:
**
** ln(X) - natural logarithm
-** log(X) - log base 10
-** log10(X) - log base 10
-** log(X,Y) - log base Y
+** log(X) - log X base 10
+** log10(X) - log X base 10
+** log(B,X) - log X base B
*/
static void logFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
- double x, y, ans;
+ double x, b, ans;
assert( argc==1 || argc==2 );
- if( sqlite3_value_type(argv[0])==SQLITE_NULL
- || (x = sqlite3_value_double(argv[0]))<0.0
- ){
- return; /* Return NULL for a domain error */
+ switch( sqlite3_value_numeric_type(argv[0]) ){
+ case SQLITE_INTEGER:
+ case SQLITE_FLOAT:
+ x = sqlite3_value_double(argv[0]);
+ if( x<0.0 ) return;
+ break;
+ default:
+ return;
}
- ans = log(x);
if( argc==2 ){
- if( sqlite3_value_type(argv[1])==SQLITE_NULL
- || (y = sqlite3_value_double(argv[1]))<0.0
- ){
- return; /* Return NULL for a domain error */
+ switch( sqlite3_value_numeric_type(argv[0]) ){
+ case SQLITE_INTEGER:
+ case SQLITE_FLOAT:
+ b = x;
+ x = sqlite3_value_double(argv[1]);
+ if( x<0.0 ) return;
+ break;
+ default:
+ return;
+ }
+ ans = log(x)/log(b);
+ }else{
+ ans = log(x);
+ switch( SQLITE_PTR_TO_INT(sqlite3_user_data(context)) ){
+ case 1:
+ /* Convert from natural logarithm to log base 10 */
+ ans *= 1.0/M_LN10;
+ break;
+ case 2:
+ /* Convert from natural logarithm to log base 2 */
+ ans *= 1.0/M_LN2;
+ break;
+ default:
+ break;
}
- ans /= log(y);
- }else if( sqlite3_user_data(context)!=0 ){
- /* Convert from natural logarithm to log base 10 */
- ans *= 0.43429448190325178672;
}
sqlite3_result_double(context, ans);
}
+
+/*
+** Functions to converts degrees to radians and radians to degrees.
+*/
+static double degToRad(double x){ return x*(M_PI/180.0); }
+static double radToDeg(double x){ return x*(180.0/M_PI); }
+
+/*
+** Implementation of 1-argument SQL math functions:
+**
+** exp(X) - Compute e to the X-th power
+*/
+static void math1Func(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ assert( argc==2 );
+ int type0;
+ double v0, ans;
+ double (*x)(double);
+ type0 = sqlite3_value_numeric_type(argv[0]);
+ if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return;
+ v0 = sqlite3_value_double(argv[0]);
+ x = (double(*)(double))sqlite3_user_data(context);
+ ans = x(v0);
+ sqlite3_result_double(context, ans);
+}
+
+/*
+** Implementation of 2-argument SQL math functions:
+**
+** power(X,Y) - Compute X to the Y-th power
+*/
+static void math2Func(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ assert( argc==2 );
+ int type0, type1;
+ double v0, v1, ans;
+ double (*x)(double,double);
+ type0 = sqlite3_value_numeric_type(argv[0]);
+ if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return;
+ type1 = sqlite3_value_numeric_type(argv[1]);
+ if( type1!=SQLITE_INTEGER && type1!=SQLITE_FLOAT ) return;
+ v0 = sqlite3_value_double(argv[0]);
+ v1 = sqlite3_value_double(argv[1]);
+ x = (double(*)(double,double))sqlite3_user_data(context);
+ ans = x(v0, v1);
+ sqlite3_result_double(context, ans);
+}
+
+/*
+** Implementation of 2-argument SQL math functions:
+**
+** power(X,Y) - Compute X to the Y-th power
+*/
+static void piFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ assert( argc==0 );
+ sqlite3_result_double(context, M_PI);
+}
+
#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */
/*
+** Implementation of sign(X) function.
+*/
+static void signFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ assert( argc==1 );
+ int type0;
+ double x;
+ type0 = sqlite3_value_numeric_type(argv[0]);
+ if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return;
+ x = sqlite3_value_double(argv[0]);
+ sqlite3_result_int(context, x<0.0 ? -1 : x>0.0 ? +1 : 0);
+}
+
+/*
** All of the FuncDef structures in the aBuiltinFunc[] array above
** to the global function hash table. This occurs at start-time (as
** a consequence of calling sqlite3_initialize()).
@@ -2091,17 +2209,41 @@ void sqlite3RegisterBuiltinFunctions(void){
#endif
FUNCTION(coalesce, 1, 0, 0, 0 ),
FUNCTION(coalesce, 0, 0, 0, 0 ),
- INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, 0 ),
- INLINE_FUNC(iif, 3, INLINEFUNC_iif, 0 ),
#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
MFUNCTION(ceil, 1, ceil, ceilingFunc ),
MFUNCTION(ceiling, 1, ceil, ceilingFunc ),
MFUNCTION(floor, 1, floor, ceilingFunc ),
+ MFUNCTION(trunc, 1, trunc, ceilingFunc ),
FUNCTION(ln, 1, 0, 0, logFunc ),
FUNCTION(log, 1, 1, 0, logFunc ),
FUNCTION(log10, 1, 1, 0, logFunc ),
+ FUNCTION(log2, 1, 2, 0, logFunc ),
FUNCTION(log, 2, 0, 0, logFunc ),
+ MFUNCTION(exp, 1, exp, math1Func ),
+ MFUNCTION(pow, 2, pow, math2Func ),
+ MFUNCTION(power, 2, pow, math2Func ),
+ MFUNCTION(mod, 2, fmod, math2Func ),
+ MFUNCTION(acos, 1, acos, math1Func ),
+ MFUNCTION(asin, 1, asin, math1Func ),
+ MFUNCTION(atan, 1, atan, math1Func ),
+ MFUNCTION(atan2, 2, atan2, math2Func ),
+ MFUNCTION(cos, 1, cos, math1Func ),
+ MFUNCTION(sin, 1, sin, math1Func ),
+ MFUNCTION(tan, 1, tan, math1Func ),
+ MFUNCTION(cosh, 1, cosh, math1Func ),
+ MFUNCTION(sinh, 1, sinh, math1Func ),
+ MFUNCTION(tanh, 1, tanh, math1Func ),
+ MFUNCTION(acosh, 1, acosh, math1Func ),
+ MFUNCTION(asinh, 1, asinh, math1Func ),
+ MFUNCTION(atanh, 1, atanh, math1Func ),
+ MFUNCTION(sqrt, 1, sqrt, math1Func ),
+ MFUNCTION(radians, 1, degToRad, math1Func ),
+ MFUNCTION(degrees, 1, radToDeg, math1Func ),
+ FUNCTION(pi, 0, 0, 0, piFunc ),
#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */
+ FUNCTION(sign, 1, 0, 0, signFunc ),
+ INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, 0 ),
+ INLINE_FUNC(iif, 3, INLINEFUNC_iif, 0 ),
};
#ifndef SQLITE_OMIT_ALTERTABLE
sqlite3AlterFunctions();