1 /* ============================================================
2  * JRobin : Pure java implementation of RRDTool's functionality
3  * ============================================================
4  *
5  * Project Info:  http://www.jrobin.org
6  * Project Lead:  Sasa Markovic (saxon@jrobin.org)
7  *
8  * Developers:    Sasa Markovic (saxon@jrobin.org)
9  *
10  *
11  * (C) Copyright 2003-2005, by Sasa Markovic.
12  *
13  * This library is free software; you can redistribute it and/or modify it under the terms
14  * of the GNU Lesser General Public License as published by the Free Software Foundation;
15  * either version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19  * See the GNU Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public License along with this
22  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
23  * Boston, MA 02111-1307, USA.
24  */

25 package org.jrobin.graph;
26
27 class ValueScaler {
28     static final String UNIT_UNKNOWN = "?";
29     static final String UNIT_SYMBOLS[] = {
30             "a""f""p""n""u""m"" ""k""M""G""T""P""E"
31     };
32     static final int SYMB_CENTER = 6;
33
34     private final double base;
35     private double magfact = -1; // nothing scaled before, rescale
36     private String unit;
37
38     ValueScaler(double base) {
39         this.base = base;
40     }
41
42     Scaled scale(double value, boolean mustRescale) {
43         Scaled scaled;
44         if (mustRescale) {
45             scaled = rescale(value);
46         }
47         else if (magfact >= 0) {
48             // already scaled, need not rescale
49             scaled = new Scaled(value / magfact, unit);
50         }
51         else {
52             // scaling not requested, but never scaled before - must rescale anyway
53             scaled = rescale(value);
54             // if zero, scale again on the next try
55             if (scaled.value == 0.0 || Double.isNaN(scaled.value)) {
56                 magfact = -1.0;
57             }
58         }
59         return scaled;
60     }
61
62     private Scaled rescale(double value) {
63         int sindex;
64         if (value == 0.0 || Double.isNaN(value)) {
65             sindex = 0;
66             magfact = 1.0;
67         }
68         else {
69             sindex = (int) (Math.floor(Math.log(Math.abs(value)) / Math.log(base)));
70             magfact = Math.pow(base, sindex);
71         }
72         if (sindex <= SYMB_CENTER && sindex >= -SYMB_CENTER) {
73             unit = UNIT_SYMBOLS[sindex + SYMB_CENTER];
74         }
75         else {
76             unit = UNIT_UNKNOWN;
77         }
78         return new Scaled(value / magfact, unit);
79     }
80
81     static class Scaled {
82         double value;
83         String unit;
84
85         public Scaled(double value, String unit) {
86             this.value = value;
87             this.unit = unit;
88         }
89
90         void dump() {
91             System.out.println("[" + value + unit + "]");
92         }
93     }
94 }
95