View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.tobago.internal.layout;
21  
22  public class MathUtils {
23  
24    /**
25     * Values smaller than this EPSILON should be treated as zero.
26     */
27    public static final double EPSILON = 0.0000001;
28  
29    /**
30     * Adjusts the list of double values to rounded values with the same sum.
31     * E. g. 2.3, 2.4, 2.5, 2.8 -> 2.0, 2.0, 3.0, 3.0
32     *
33     * @param list
34     */
35    public static void adjustRemainders(double[] list, double bias) {
36      for (double v : list) {
37        double lastBias;
38        if (bias < 0.0) {
39          lastBias = findAndAdjustMaxRemainder(list);
40        } else {
41          lastBias = findAndAdjustMinRemainder(list);
42        }
43        if (isZero(lastBias)) {
44          break;
45        }
46        bias += lastBias;
47      }
48  
49      assert isZero(bias);
50    }
51  
52    public static double findAndAdjustMaxRemainder(double[] list) {
53      double max = 0.0;
54      Integer indexOfMax = null;
55      for (int i = 0; i < list.length; i++) {
56        double remainder = remainder(list[i]);
57        if (remainder > max + EPSILON) {
58          max = remainder;
59          indexOfMax = i;
60        }
61      }
62      if (indexOfMax != null) {
63        list[indexOfMax] += 1.0 - max;
64        return 1.0 - max;
65      }
66      return 0.0;
67    }
68  
69    public static double findAndAdjustMinRemainder(double[] list) {
70      double min = 1.0;
71      Integer indexOfMin = null;
72      for (int i = 0; i < list.length; i++) {
73        double remainder = remainder(list[i]);
74        if (remainder == 0) { // is zero
75          continue;
76        }
77        if (remainder < min - EPSILON) {
78          min = remainder;
79          indexOfMin = i;
80        }
81      }
82      if (indexOfMin != null) {
83        list[indexOfMin] -= min;
84        return -min;
85      }
86      return 0.0;
87    }
88  
89    public static double remainder(double v) {
90      return v - Math.floor(v);
91    }
92  
93    public static boolean isZero(double factor) {
94      return Math.abs(factor) < EPSILON;
95    }
96  
97    public static boolean isNotZero(double factor) {
98      return Math.abs(factor) >= EPSILON;
99    }
100 
101   public static boolean isInteger(double value) {
102     return isZero(value - Math.round(value));
103   }
104 
105   public static boolean isNotInteger(double value) {
106     return isNotZero(value - Math.round(value));
107   }
108 }