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 final 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    private MathUtils() {
30    }
31  
32    /**
33     * Adjusts the list of double values to rounded values with the same sum.
34     * E. g. 2.3, 2.4, 2.5, 2.8 -> 2.0, 2.0, 3.0, 3.0
35     */
36    public static void adjustRemainders(final double[] list, double bias) {
37      for (final double ignored : list) {
38        final double lastBias;
39        if (bias < 0.0) {
40          lastBias = findAndAdjustMaxRemainder(list);
41        } else {
42          lastBias = findAndAdjustMinRemainder(list);
43        }
44        if (isZero(lastBias)) {
45          break;
46        }
47        bias += lastBias;
48      }
49  
50      assert isZero(bias);
51    }
52  
53    public static double findAndAdjustMaxRemainder(final double[] list) {
54      double max = 0.0;
55      Integer indexOfMax = null;
56      for (int i = 0; i < list.length; i++) {
57        double remainder = remainder(list[i]);
58        if (remainder > max + EPSILON) {
59          max = remainder;
60          indexOfMax = i;
61        }
62      }
63      if (indexOfMax != null) {
64        list[indexOfMax] += 1.0 - max;
65        return 1.0 - max;
66      }
67      return 0.0;
68    }
69  
70    public static double findAndAdjustMinRemainder(final double[] list) {
71      double min = 1.0;
72      Integer indexOfMin = null;
73      for (int i = 0; i < list.length; i++) {
74        final double remainder = remainder(list[i]);
75        if (remainder == 0) { // is zero
76          continue;
77        }
78        if (remainder < min - EPSILON) {
79          min = remainder;
80          indexOfMin = i;
81        }
82      }
83      if (indexOfMin != null) {
84        list[indexOfMin] -= min;
85        return -min;
86      }
87      return 0.0;
88    }
89  
90    public static double remainder(final double v) {
91      return v - Math.floor(v);
92    }
93  
94    public static boolean isZero(final double factor) {
95      return Math.abs(factor) < EPSILON;
96    }
97  
98    public static boolean isNotZero(final double factor) {
99      return Math.abs(factor) >= EPSILON;
100   }
101 
102   public static boolean isInteger(final double value) {
103     return isZero(value - Math.round(value));
104   }
105 
106   public static boolean isNotInteger(final double value) {
107     return isNotZero(value - Math.round(value));
108   }
109 }