001         package com.croftsoft.core.math;
002    
003         import java.awt.geom.Point2D;
004         import java.util.*;
005    
006         /*********************************************************************
007         * A collection of static methods to supplement java.lang.Math.
008         *
009         * @version
010         *   $Id: MathLib.java,v 1.5 2008/08/09 02:10:33 croft Exp $
011         * @since
012         *   1998-12-27
013         * @author
014         *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
015         *********************************************************************/
016    
017         public final class  MathLib
018         //////////////////////////////////////////////////////////////////////
019         //////////////////////////////////////////////////////////////////////
020         {
021    
022         public static void  main ( String [ ]  args )
023         //////////////////////////////////////////////////////////////////////
024         {
025           System.out.println ( test ( ) );
026         }
027         
028         public static boolean  test ( )
029         //////////////////////////////////////////////////////////////////////
030         {
031           return ( greatestCommonFactor ( 6, 15 ) == 3 )
032             && ( log (   1.0, 10.0 ) ==  0.0 )
033             && ( log (  10.0, 10.0 ) ==  1.0 )
034             && ( log ( 100.0, 10.0 ) ==  2.0 )
035             && ( log (   0.5,  2.0 ) == -1.0 )
036             && ( log (   1.0,  2.0 ) ==  0.0 )
037             && ( log (   2.0,  2.0 ) ==  1.0 )
038             && ( log (   4.0,  2.0 ) ==  2.0 )
039             && ( wrap ( -190, -180, 360 ) ==  170 )
040             && ( wrap ( -180, -180, 360 ) == -180 )
041             && ( wrap (  180, -180, 360 ) == -180 )
042             && ( wrap (  190, -180, 360 ) == -170 )
043             && ( wrap (  370, -180, 360 ) ==   10 )
044             && ( wrap (  -10,    0, 360 ) ==  350 )
045             && ( wrap (    0,    0, 360 ) ==    0 )
046             && ( wrap (   10,    0, 360 ) ==   10 )
047             && ( wrap (  360,    0, 360 ) ==    0 )
048             && ( wrap (  370,    0, 360 ) ==   10 );
049         }
050    
051         //////////////////////////////////////////////////////////////////////
052         //////////////////////////////////////////////////////////////////////
053         
054         public static double  clip (
055           final double  value,
056           final double  minimum,
057           final double  maximum )
058         //////////////////////////////////////////////////////////////////////
059         {
060           if ( minimum > maximum )
061           {
062             throw new IllegalArgumentException (
063               "minimum > maximum:  " + minimum + ", " + maximum );
064           }
065           
066           return
067             value < minimum ? minimum : value > maximum ? maximum : value;
068         }
069    
070         /*********************************************************************
071         * Cumulative Distribution Function (CDF).
072         * 
073         * @see
074         *   http://en.wikipedia.org/wiki/Exponential_distribution
075         *   #Cumulative_distribution_function
076         *********************************************************************/
077         public static double  cumulative (
078           double  x,
079           double  lambda )
080         //////////////////////////////////////////////////////////////////////
081         {
082           if ( x <= 0.0 )
083           {
084             return 0.0;
085           }
086           
087           return 1.0 - Math.exp ( -lambda * x );
088         }
089    
090         /*********************************************************************
091         * return cumulative ( x, 1 );
092         *********************************************************************/
093         public static double  cumulative ( double  x )
094         //////////////////////////////////////////////////////////////////////
095         {
096           return cumulative ( x, 1 );
097         }
098    
099         @SuppressWarnings ( "all" ) // TODO:  fix argument assignment warning
100         public static List<Integer>  factor ( int  n )
101         //////////////////////////////////////////////////////////////////////
102         {
103           if ( n < 0 )
104           {
105             throw new IllegalArgumentException ( "n < 0" );
106           }
107    
108           List<Integer>  primeList = new ArrayList<Integer> ( );
109    
110           if ( n == 0 )
111           {
112             primeList.add ( new Integer ( 0 ) );
113    
114             return primeList;
115           }
116    
117           if ( n == 1 )
118           {
119             primeList.add ( new Integer ( 1 ) );
120    
121             return primeList;
122           }
123    
124           for ( int  i = 2; i <= n; i++ )
125           {
126             if ( n % i == 0 )
127             {
128               primeList.add ( new Integer ( i ) );
129    
130               n = n / i;
131    
132               i = 1;
133             }
134           }
135    
136           return primeList;
137         }
138    
139         public static int  greatestCommonFactor (
140           int  n0,
141           int  n1 )
142         //////////////////////////////////////////////////////////////////////
143         {
144           int  gcf = 1;
145    
146           List<Integer>  primeList0 = factor ( n0 );
147    
148           List<Integer>  primeList1 = factor ( n1 );
149    
150           Integer [ ]  primeArray0
151             = primeList0.toArray ( new Integer [ 0 ] );
152    
153           for ( int  i = 0; i < primeArray0.length; i++ )
154           {
155             Integer  j = primeArray0 [ i ];
156    
157             if ( primeList1.contains ( j ) )
158             {
159               gcf = gcf * j.intValue ( );
160    
161               primeList1.remove ( j );
162             }
163           }
164    
165           return gcf;
166         }
167    
168         /*********************************************************************
169         * Calculates the logarithm in the given base.
170         *
171         * <code><pre>return Math.log ( a ) / Math.log ( base );</pre></code>
172         *********************************************************************/
173         public static double  log (
174           double  a,
175           double  base )
176         //////////////////////////////////////////////////////////////////////
177         {
178           return Math.log ( a ) / Math.log ( base );
179         }
180    
181         /*********************************************************************
182         * Also known as the "logistic function".
183         *********************************************************************/
184         public static double  sigmoid ( double  a )
185         //////////////////////////////////////////////////////////////////////
186         {
187           return 1.0 / ( 1.0 + Math.exp ( -a ) );
188         }
189    
190         /*********************************************************************
191         * The derivative with respect to the argument.
192         *********************************************************************/
193         public static double  sigmoidDerivative ( double  a )
194         //////////////////////////////////////////////////////////////////////
195         {
196           double  y = sigmoid ( a );
197           return y * ( 1.0 - y );
198         }
199    
200         /*********************************************************************
201         * Returns +1 if positive, -1 if negative, otherwise 0.
202         *********************************************************************/
203         public static byte  signum ( long  l )
204         //////////////////////////////////////////////////////////////////////
205         {
206           return ( byte ) ( l > 0 ? 1 : ( l < 0 ? -1 : 0 ) );
207         }
208    
209         /*********************************************************************
210         * hyperbolic tangent = 2 * sigmoid ( 2 * a ) - 1
211         *********************************************************************/
212         public static double  tanh ( double  a )
213         //////////////////////////////////////////////////////////////////////
214         {
215           return 2.0 * sigmoid ( 2.0 * a ) - 1.0;
216         }
217    
218         /*********************************************************************
219         * Converts from polar to rectangular coordinates.
220         *********************************************************************/
221         public static void  toRectangular (
222           double   radius,
223           double   angle,
224           Point2D  point2D )
225         //////////////////////////////////////////////////////////////////////
226         {
227           point2D.setLocation (
228             radius * Math.cos ( angle ),
229             radius * Math.sin ( angle ) );
230         }
231    
232         /*********************************************************************
233         * Converts from polar to rectangular coordinates.
234         *********************************************************************/
235         public static Point2D  toRectangular (
236           double  radius,
237           double  angle )
238         //////////////////////////////////////////////////////////////////////
239         {
240           Point2D  point2D = new Point2D.Double ( );
241    
242           toRectangular ( radius, angle, point2D );
243    
244           return point2D;
245         }
246         
247         /*********************************************************************
248         * Wraps the value to [minimum, minimum + range).
249         * 
250         * Example:  wrap ( -190, -180, 360 ) ==>  170
251         * Example:  wrap (  190, -180, 360 ) ==>  -10
252         * Example:  wrap (  360, -180, 360 ) ==> -180
253         *********************************************************************/
254         public static double  wrap (
255           final double  value,
256           final double  minimum,
257           final double  range )
258         //////////////////////////////////////////////////////////////////////
259         {
260           if ( range <= 0 )
261           {
262             throw new IllegalArgumentException ( "range <= 0:  " + range );
263           }
264           
265           final double  maximum = minimum + range;
266           
267           if ( ( value >= minimum )
268             && ( value <  maximum ) )
269           {
270             return value;
271           }
272           
273           if ( value < minimum )
274           {
275             return value + Math.ceil ( ( minimum - value ) / range ) * range;
276           }
277    
278           return value
279             - ( 1 + Math.floor ( ( value - maximum ) / range ) ) * range;
280         }
281    
282         //////////////////////////////////////////////////////////////////////
283         //////////////////////////////////////////////////////////////////////
284    
285         private  MathLib ( )
286         //////////////////////////////////////////////////////////////////////
287         {
288           // empty
289         }
290    
291         //////////////////////////////////////////////////////////////////////
292         //////////////////////////////////////////////////////////////////////
293         }