/* File: DasMath.java * Copyright (C) 2002-2003 The University of Iowa * Created by: Jeremy Faden * Jessica Swanner * Edward E. West * * This file is part of the das2 library. * * das2 is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.das2.util; import java.util.logging.Level; import java.util.logging.Logger; /** * * @author jbf */ public class DasMath { /** Creates a new instance of DasMath */ public DasMath() { } private static final double log10=Math.log(10); public static double log10(double x) { return Math.log(x)/log10; } public static double exp10(double x) { double result= Math.pow(10,x); return result; } public static double exp10(int x) { double result= Math.pow(10,x); return result; } /** * round the decimal to the number of fractional decimal places. For example, * DasMath.roundNFractionalDigits(1.2345678,3)==1.23 * Note the name implies that there will be three decimals in the fractional * part, but this implementation will return only two. * * @param x a double * @param n number of decimal places * @return the number rounded to the number of decimal places. * @see #roundNSignificantDigits(double, int) * @see https://github.com/autoplot/dev/blob/master/demos/2023/20230910/roundNDigits.jy */ public static double roundNFractionalDigits(double x,int n) { double tenToN= Math.pow(10,n-1); return Math.round( x * tenToN ) / tenToN; } /** * Round the double to n significant digits by removing the exponent to make the number order one, * then rounding the mantissa, then replacing the exponent. * @param x a double * @param n number of decimal places * @return the number rounded to the number of decimal places. * @see #roundNFractionalDigits(double, int) * @see https://github.com/autoplot/dev/blob/master/demos/2023/20230910/roundNDigits.jy */ public static double roundNSignificantDigits(double x,int n) { double sign= x<0 ? -1 : 1; double exp= Math.pow(10,Math.floor(Math.log10(sign*x))); double mant= x/exp; double tenToN= Math.pow(10,n-1); mant= Math.round( mant * tenToN ) / tenToN; return mant*exp; } public static double tanh( double x ) { double sinh = ( Math.exp(x) - Math.exp(-x) )/2; double cosh = ( Math.exp(x) + Math.exp(-x) )/2; double tanh = sinh / cosh; return tanh; } /** Interpolate just one point */ public static double interpolate( double[] datay, double findex ) { int index= (int)findex; double alpha= findex - index; double result; if ( findex<0. ) return datay[0]; if ( findex>datay.length-1. ) return datay[datay.length-1]; if ( alpha == 0. ) { // optimization and handle findex=(data.length-1); result= datay[index]; } else { result= datay[index] * ( 1.0 - alpha ) + datay[index+1] * alpha ; } return result; } /** interpolate an array of points. */ public static double[] interpolate( double[] datay, double[] findex ) { double[] result= new double[ findex.length ]; for ( int i=0; i0 && datax[index]>x ) index--; if ( index==datax.length-1 ) index--; return index + ( x - datax[index] ) / ( datax[index+1] - datax[index] ); } public static void main(String[] args) { double x= 1e-18; Logger.getLogger("das2.anon").log(Level.FINEST, "x:{0}", x); Logger.getLogger("das2.anon").log(Level.FINEST, "roundNDigits:{0}", roundNSignificantDigits(x,3)); double[] x1= new double[] { 1,2,3,4,5 }; double[] y1= new double[] { 4,6,7,3,1 }; double[] interpx= new double [] { 1.0, 1.5, 4.5, 5.0, 1.5 }; double[] interpy= interpolate( y1, findex( x1, interpx ) ); for ( int i=0; i= 0 ? result : t + result; } /** * just like modulo (%) function, but negative numbers return positive phase. * @param x the numerator * @param t the devisor * @return the modulo, which will always be positive */ public static int modp( int x, int t) { int result= x % t; return result >= 0 ? result : t + result; } /** * returns the bigger number of two numbers * @param x1 a number * @param x2 a number * @return the greater of the two numbers */ public static double biggerOf(double x1, double x2) { return ( x1>x2 ) ? x1 : x2; } private static double gcd( double a, double d, double error ) { if ( error>0 ) { a= Math.round( a/error ); d= Math.round( d/error ); } if ( a0 ) { return a * error; } else { return a; } } double r= a % d; int iterations=0; while ( r > 0 && iterations<15 ) { d= r; r= a % d; iterations++; } if ( error>0 ) { return d * error; } else { return d; } } /** * Returns the greatest common divisor of a group of numbers. This is useful for * a number of visualization techniques, for instance when you need to integerize * your data, the binsize should be the gcd. An error parameter is provided to * avoid numerical noise, and in case there is a granularity that needn't be * surpassed. * * org.das2.datum.DatumUtil has a private copy of this code. * @param A the array of numbers * @param error the limit of the error to deal with numerical noise * @return the greatest common divisor (GCD) */ public static double gcd( double[] A, double error ) { double guess= A[0]; double result= guess; for ( int i=1; i A[i] ? max : A[i] ); } return max; } /** * return the minimum of the list * @param A the list * @return the minimum of the list */ public static double min( double[] A ) { double min= A[0]; for ( int i=0; i