File indexing completed on 2024-05-12 15:27:08

0001 /***************************************************************************
0002     File                 : nsl_math.c
0003     Project              : LabPlot
0004     Description          : NSL math functions
0005     --------------------------------------------------------------------
0006     Copyright            : (C) 2018-2020 by Stefan Gerlach (stefan.gerlach@uni.kn)
0007 
0008  ***************************************************************************/
0009 
0010 /***************************************************************************
0011  *                                                                         *
0012  *  This program is free software; you can redistribute it and/or modify   *
0013  *  it under the terms of the GNU General Public License as published by   *
0014  *  the Free Software Foundation; either version 2 of the License, or      *
0015  *  (at your option) any later version.                                    *
0016  *                                                                         *
0017  *  This program is distributed in the hope that it will be useful,        *
0018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
0019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
0020  *  GNU General Public License for more details.                           *
0021  *                                                                         *
0022  *   You should have received a copy of the GNU General Public License     *
0023  *   along with this program; if not, write to the Free Software           *
0024  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
0025  *   Boston, MA  02110-1301  USA                                           *
0026  *                                                                         *
0027  ***************************************************************************/
0028 
0029 #include "nsl_math.h"
0030 #include <gsl/gsl_math.h>
0031 
0032 bool nsl_math_approximately_equal(double a, double b) {
0033     return nsl_math_approximately_equal_eps(a, b, 1.e-7);
0034 }
0035 
0036 bool nsl_math_approximately_equal_eps(double a, double b, double epsilon) {
0037         return fabs(a - b) <= ( (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon);
0038 }
0039 
0040 bool nsl_math_essentially_equal(double a, double b) {
0041     return nsl_math_essentially_equal_eps(a, b, 1.e-7);
0042 }
0043 
0044 bool nsl_math_essentially_equal_eps(double a, double b, double epsilon) {
0045         return fabs(a - b) <= ( (fabs(a) > fabs(b) ? fabs(b) : fabs(a)) * epsilon);
0046 }
0047 
0048 bool nsl_math_definitely_greater_than(double a, double b) {
0049     return nsl_math_definitely_greater_than_eps(a, b, 1.e-7);
0050 }
0051 
0052 bool nsl_math_definitely_greater_than_eps(double a, double b, double epsilon) {
0053         return (a - b) > ( (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon);
0054 }
0055 
0056 bool nsl_math_definitely_less_than(double a, double b) {
0057     return nsl_math_definitely_less_than_eps(a, b, 1.e-7);
0058 }
0059 
0060 bool nsl_math_definitely_less_than_eps(double a, double b, double epsilon) {
0061         return (b - a) > ( (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon);
0062 }
0063 
0064 
0065 
0066 int nsl_math_decimal_places(double value) {
0067     return -(int)floor(log10(fabs(value)));
0068 }
0069 
0070 int nsl_math_rounded_decimals(double value) {
0071     int places = nsl_math_decimal_places(value);
0072 
0073 // printf("places = %d, rv = %g\n", places, round(fabs(value) * pow(10, places)));
0074     if (round(fabs(value) * gsl_pow_int(10., places)) >= 5.)
0075         places--;
0076 
0077     return places;
0078 }
0079 
0080 int nsl_math_rounded_decimals_max(double value, int max) {
0081     return GSL_MIN_INT(max, nsl_math_rounded_decimals(value));
0082 }
0083 
0084 double nsl_math_round_places(double value, unsigned int n) {
0085     // no need to round
0086     if (value == 0. || fabs(value) > 1.e16 || fabs(value) < 1.e-16 || isnan(value) || isinf(value))
0087         return value;
0088 
0089     double scale = gsl_pow_uint(10., n);
0090     double scaled_value = value*scale;
0091     if (fabs(scaled_value) > 1.e16)
0092         return value;
0093     if (fabs(scaled_value) < .5)
0094         return 0.;
0095 
0096     return round(scaled_value)/scale;
0097 }
0098 
0099 double nsl_math_round_precision(double value, unsigned int p) {
0100     // no need to round
0101     if (value == 0. || p > 16 || isnan(value) || isinf(value))
0102         return value;
0103 
0104     int e = 0;
0105     while (fabs(value) > 10.) {
0106         value /= 10.;
0107         e++;
0108     }
0109     while (fabs(value) < 1.) {
0110         value *= 10.;
0111         e--;
0112     }
0113 
0114     double scale = gsl_pow_uint(10., p);
0115     double scaled_value = value*scale;
0116 
0117     return round(scaled_value)/scale * gsl_pow_int(10., e);
0118 }