create changelog entry
[debian/openrocket] / android-libraries / achartengine / src / org / achartengine / util / MathHelper.java
1 /**\r
2  * Copyright (C) 2009 - 2012 SC 4ViewSoft SRL\r
3  *  \r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  *  \r
8  *      http://www.apache.org/licenses/LICENSE-2.0\r
9  *  \r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  */\r
16 package org.achartengine.util;\r
17 \r
18 import java.text.NumberFormat;\r
19 import java.text.ParseException;\r
20 import java.util.ArrayList;\r
21 import java.util.List;\r
22 \r
23 /**\r
24  * Utility class for math operations.\r
25  */\r
26 public class MathHelper {\r
27   /** A value that is used a null value. */\r
28   public static final double NULL_VALUE = Double.MAX_VALUE;\r
29   /**\r
30    * A number formatter to be used to make sure we have a maximum number of\r
31    * fraction digits in the labels.\r
32    */\r
33   private static final NumberFormat FORMAT = NumberFormat.getNumberInstance();\r
34 \r
35   private MathHelper() {\r
36     // empty constructor\r
37   }\r
38 \r
39   /**\r
40    * Calculate the minimum and maximum values out of a list of doubles.\r
41    * \r
42    * @param values the input values\r
43    * @return an array with the minimum and maximum values\r
44    */\r
45   public static double[] minmax(List<Double> values) {\r
46     if (values.size() == 0) {\r
47       return new double[2];\r
48     }\r
49     double min = values.get(0);\r
50     double max = min;\r
51     int length = values.size();\r
52     for (int i = 1; i < length; i++) {\r
53       double value = values.get(i);\r
54       min = Math.min(min, value);\r
55       max = Math.max(max, value);\r
56     }\r
57     return new double[] { min, max };\r
58   }\r
59 \r
60   /**\r
61    * Computes a reasonable set of labels for a data interval and number of\r
62    * labels.\r
63    * \r
64    * @param start start value\r
65    * @param end final value\r
66    * @param approxNumLabels desired number of labels\r
67    * @return collection containing {start value, end value, increment}\r
68    */\r
69   public static List<Double> getLabels(final double start, final double end,\r
70       final int approxNumLabels) {\r
71     FORMAT.setMaximumFractionDigits(5);\r
72     List<Double> labels = new ArrayList<Double>();\r
73     double[] labelParams = computeLabels(start, end, approxNumLabels);\r
74     // when the start > end the inc will be negative so it will still work\r
75     int numLabels = 1 + (int) ((labelParams[1] - labelParams[0]) / labelParams[2]);\r
76     // we want the range to be inclusive but we don't want to blow up when\r
77     // looping for the case where the min and max are the same. So we loop\r
78     // on\r
79     // numLabels not on the values.\r
80     for (int i = 0; i < numLabels; i++) {\r
81       double z = labelParams[0] + i * labelParams[2];\r
82       try {\r
83         // this way, we avoid a label value like 0.4000000000000000001 instead\r
84         // of 0.4\r
85         z = FORMAT.parse(FORMAT.format(z)).doubleValue();\r
86       } catch (ParseException e) {\r
87         // do nothing here\r
88       }\r
89       labels.add(z);\r
90     }\r
91     return labels;\r
92   }\r
93 \r
94   /**\r
95    * Computes a reasonable number of labels for a data range.\r
96    * \r
97    * @param start start value\r
98    * @param end final value\r
99    * @param approxNumLabels desired number of labels\r
100    * @return double[] array containing {start value, end value, increment}\r
101    */\r
102   private static double[] computeLabels(final double start, final double end,\r
103       final int approxNumLabels) {\r
104     if (Math.abs(start - end) < 0.0000001f) {\r
105       return new double[] { start, start, 0 };\r
106     }\r
107     double s = start;\r
108     double e = end;\r
109     boolean switched = false;\r
110     if (s > e) {\r
111       switched = true;\r
112       double tmp = s;\r
113       s = e;\r
114       e = tmp;\r
115     }\r
116     double xStep = roundUp(Math.abs(s - e) / approxNumLabels);\r
117     // Compute x starting point so it is a multiple of xStep.\r
118     double xStart = xStep * Math.ceil(s / xStep);\r
119     double xEnd = xStep * Math.floor(e / xStep);\r
120     if (switched) {\r
121       return new double[] { xEnd, xStart, -1.0 * xStep };\r
122     }\r
123     return new double[] { xStart, xEnd, xStep };\r
124   }\r
125 \r
126   /**\r
127    * Given a number, round up to the nearest power of ten times 1, 2, or 5. The\r
128    * argument must be strictly positive.\r
129    */\r
130   private static double roundUp(final double val) {\r
131     int exponent = (int) Math.floor(Math.log10(val));\r
132     double rval = val * Math.pow(10, -exponent);\r
133     if (rval > 5.0) {\r
134       rval = 10.0;\r
135     } else if (rval > 2.0) {\r
136       rval = 5.0;\r
137     } else if (rval > 1.0) {\r
138       rval = 2.0;\r
139     }\r
140     rval *= Math.pow(10, exponent);\r
141     return rval;\r
142   }\r
143 \r
144   /**\r
145    * Transforms a list of Float values into an array of float.\r
146    * \r
147    * @param values the list of Float\r
148    * @return the array of floats\r
149    */\r
150   public static float[] getFloats(List<Float> values) {\r
151     int length = values.size();\r
152     float[] result = new float[length];\r
153     for (int i = 0; i < length; i++) {\r
154       result[i] = values.get(i).floatValue();\r
155     }\r
156     return result;\r
157   }\r
158 \r
159   /**\r
160    * Transforms a list of Double values into an array of double.\r
161    * \r
162    * @param values the list of Double\r
163    * @return the array of doubles\r
164    */\r
165   public static double[] getDoubles(List<Double> values) {\r
166     int length = values.size();\r
167     double[] result = new double[length];\r
168     for (int i = 0; i < length; i++) {\r
169       result[i] = values.get(i).doubleValue();\r
170     }\r
171     return result;\r
172   }\r
173 \r
174 }\r