001    package edu.nrao.sss.measure;
002    
003    import java.math.BigDecimal;
004    import java.math.RoundingMode;
005    
006    import static edu.nrao.sss.math.MathUtil.MC_FINAL_CALC;
007    import static edu.nrao.sss.math.MathUtil.MC_INTERM_CALCS;
008    
009    import edu.nrao.sss.util.EnumerationUtility;
010    import edu.nrao.sss.util.StringUtil;
011    import edu.nrao.sss.util.Symbolic;
012    
013    /**
014     * Units of measure for frequencies.
015     * <p>
016     * <b><u>Table of Units</u></b></p>
017     * <p style="margin-left:1.5em">
018     * <table border="1" cellspacing="0">
019     *   <tr BGCOLOR="#EEEEFF"><th>Element</th>  <th>Name(s)<sup>1</sup></th>
020     *       <th>Symbol(s)<sup>2</sup></th>  <th>Cycles per<br/>Second</th></tr>
021     *   <tr><td>YOCTOHERTZ</td><td>YOCTOHERTZ</td>
022     *       <td align="center">yHz</td><td>10<sup>-24</sup></td></tr>
023     *   <tr><td>ZEPTOHERTZ</td><td>ZEPTOHERTZ</td>
024     *       <td align="center">zHz</td><td>10<sup>-21</sup></td></tr>
025     *   <tr><td>ATTOHERTZ</td><td>ATTOHERTZ</td>
026     *       <td align="center">aHz</td><td>10<sup>-18</sup></td></tr>
027     *   <tr><td>FEMTOHERTZ</td><td>FEMTOHERTZ</td>
028     *       <td align="center">fHz</td><td>10<sup>-15</sup></td></tr>
029     *   <tr><td>PICOHERTZ</td><td>PICOHERTZ</td>
030     *       <td align="center">pHz</td><td>10<sup>-12</sup></td></tr>
031     *   <tr><td>NANOHERTZ</td><td>NANOHERTZ</td>
032     *       <td align="center">nHz</td><td>10<sup>-9</sup></td></tr>
033     *   <tr><td>MICROHERTZ</td><td>MICROHERTZ</td>
034     *       <td align="center">&#x00B5;Hz</td><td>10<sup>-6</sup></td></tr>
035     *   <tr><td>MILLIHERTZ</td><td>MILLIHERTZ</td>
036     *       <td align="center">mHz</td><td>0.001</td></tr>
037     *   <tr><td>CENTIHERTZ</td><td>CENTIHERTZ</td>
038     *       <td align="center">cHz</td><td>0.01</td></tr>
039     *   <tr><td>DECIHERTZ</td><td>DECIHERTZ</td>
040     *       <td align="center">dHz</td><td>0.1</td></tr>
041     *   <tr><td>HERTZ</td><td>HERTZ</td>
042     *       <td align="center">Hz</td><td>1.0</td></tr>
043     *   <tr><td>DECAHERTZ</td><td>DECAHERTZ</td>
044     *       <td align="center">daHz</td><td>10.0</td></tr>
045     *   <tr><td>HECTOHERTZ</td><td>HECTOHERTZ</td>
046     *       <td align="center">hHz</td><td>100.0</td></tr>
047     *   <tr><td>KILOHERTZ</td><td>KILOHERTZ</td>
048     *       <td align="center">kHz</td><td>1,000.0</td></tr>
049     *   <tr><td>MEGAHERTZ</td><td>MEGAHERTZ</td>
050     *       <td align="center">MHz</td><td>10<sup>6</sup></td></tr>
051     *   <tr><td>GIGAHERTZ</td><td>GIGAHERTZ</td>
052     *       <td align="center">GHz</td><td>10<sup>9</sup></td></tr>
053     *   <tr><td>TERAHERTZ</td><td>TERAHERTZ</td>
054     *       <td align="center">THz</td><td>10<sup>12</sup></td></tr>
055     *   <tr><td>PETAHERTZ</td><td>PETAHERTZ</td>
056     *       <td align="center">PHz</td><td>10<sup>15</sup></td></tr>
057     *   <tr><td>ETAHERTZ</td><td>ETAHERTZ</td>
058     *       <td align="center">EHz</td><td>10<sup>18</sup></td></tr>
059     *   <tr><td>ZETTAHERTZ</td><td>ZETTAHERTZ</td>
060     *       <td align="center">ZHz</td><td>10<sup>21</sup></td></tr>
061     *   <tr><td>YOTTAHERTZ</td><td>YOTTAHERTZ</td>
062     *       <td align="center">YHz</td><td>10<sup>24</sup></td></tr>
063     * </table>
064     * <sup><b>1</b></sup>The names in this column may be sent to
065     * {@link #fromString(String)}.  Note that the names are
066     * not case sensitive.<br/>
067     * <sup><b>2</b></sup>The symbols in this column may be sent to
068     * {@link #fromString(String)}.  Note that the symbols <i>are</i>
069     * case sensitive.
070     * </p>
071     * <p>
072     * <b><u>Table of Conversion Factors<sup>3</sup></u></b></p>
073     * <p style="margin-left:1.5em">
074     * <table border="1" cellspacing="0">
075     * <tr BGCOLOR="#EEEEFF"><th> </th><th>yHz</th><th>zHz</th><th>aHz</th><th>fHz</th><th>pHz</th><th>nHz</th><th>&#x00B5;Hz</th><th>mHz</th><th>cHz</th><th>dHz</th><th>Hz</th><th>daHz</th><th>hHz</th><th>kHz</th><th>MHz</th><th>GHz</th><th>THz</th><th>PHz</th><th>EHz</th><th>ZHz</th><th>YHz</th></tr>
076     * <tr><td>YOCTOHERTZ</td><td align="right">1.0</td><td align="right">0.0010</td><td align="right">0.0000010</td><td align="right">1.0E-9</td><td align="right">1.0E-12</td><td align="right">1.0E-15</td><td align="right">1.0E-18</td><td align="right">1.0E-21</td><td align="right">1.0E-22</td><td align="right">1.0E-23</td><td align="right">1.0E-24</td><td align="right">1.0E-25</td><td align="right">1.0E-26</td><td align="right">1.0E-27</td><td align="right">1.0E-30</td><td align="right">1.0E-33</td><td align="right">1.0E-36</td><td align="right">1.0E-39</td><td align="right">1.0E-42</td><td align="right">1.0E-45</td><td align="right">1.0E-48</td></tr>
077     * <tr><td>ZEPTOHERTZ</td><td align="right">1.0E+3</td><td align="right">1.0</td><td align="right">0.0010</td><td align="right">0.0000010</td><td align="right">1.0E-9</td><td align="right">1.0E-12</td><td align="right">1.0E-15</td><td align="right">1.0E-18</td><td align="right">1.0E-19</td><td align="right">1.0E-20</td><td align="right">1.0E-21</td><td align="right">1.0E-22</td><td align="right">1.0E-23</td><td align="right">1.0E-24</td><td align="right">1.0E-27</td><td align="right">1.0E-30</td><td align="right">1.0E-33</td><td align="right">1.0E-36</td><td align="right">1.0E-39</td><td align="right">1.0E-42</td><td align="right">1.0E-45</td></tr>
078     * <tr><td>ATTOHERTZ</td><td align="right">1.0E+6</td><td align="right">1.0E+3</td><td align="right">1.0</td><td align="right">0.0010</td><td align="right">0.0000010</td><td align="right">1.0E-9</td><td align="right">1.0E-12</td><td align="right">1.0E-15</td><td align="right">1.0E-16</td><td align="right">1.0E-17</td><td align="right">1.0E-18</td><td align="right">1.0E-19</td><td align="right">1.0E-20</td><td align="right">1.0E-21</td><td align="right">1.0E-24</td><td align="right">1.0E-27</td><td align="right">1.0E-30</td><td align="right">1.0E-33</td><td align="right">1.0E-36</td><td align="right">1.0E-39</td><td align="right">1.0E-42</td></tr>
079     * <tr><td>FEMTOHERTZ</td><td align="right">1.0E+9</td><td align="right">1.0E+6</td><td align="right">1.0E+3</td><td align="right">1.0</td><td align="right">0.0010</td><td align="right">0.0000010</td><td align="right">1.0E-9</td><td align="right">1.0E-12</td><td align="right">1.0E-13</td><td align="right">1.0E-14</td><td align="right">1.0E-15</td><td align="right">1.0E-16</td><td align="right">1.0E-17</td><td align="right">1.0E-18</td><td align="right">1.0E-21</td><td align="right">1.0E-24</td><td align="right">1.0E-27</td><td align="right">1.0E-30</td><td align="right">1.0E-33</td><td align="right">1.0E-36</td><td align="right">1.0E-39</td></tr>
080     * <tr><td>PICOHERTZ</td><td align="right">1.0E+12</td><td align="right">1.0E+9</td><td align="right">1.0E+6</td><td align="right">1.0E+3</td><td align="right">1.0</td><td align="right">0.0010</td><td align="right">0.0000010</td><td align="right">1.0E-9</td><td align="right">1.0E-10</td><td align="right">1.0E-11</td><td align="right">1.0E-12</td><td align="right">1.0E-13</td><td align="right">1.0E-14</td><td align="right">1.0E-15</td><td align="right">1.0E-18</td><td align="right">1.0E-21</td><td align="right">1.0E-24</td><td align="right">1.0E-27</td><td align="right">1.0E-30</td><td align="right">1.0E-33</td><td align="right">1.0E-36</td></tr>
081     * <tr><td>NANOHERTZ</td><td align="right">1.0E+15</td><td align="right">1.0E+12</td><td align="right">1.0E+9</td><td align="right">1.0E+6</td><td align="right">1.0E+3</td><td align="right">1.0</td><td align="right">0.0010</td><td align="right">0.0000010</td><td align="right">1.0E-7</td><td align="right">1.0E-8</td><td align="right">1.0E-9</td><td align="right">1.0E-10</td><td align="right">1.0E-11</td><td align="right">1.0E-12</td><td align="right">1.0E-15</td><td align="right">1.0E-18</td><td align="right">1.0E-21</td><td align="right">1.0E-24</td><td align="right">1.0E-27</td><td align="right">1.0E-30</td><td align="right">1.0E-33</td></tr>
082     * <tr><td>MICROHERTZ</td><td align="right">1.0E+18</td><td align="right">1.0E+15</td><td align="right">1.0E+12</td><td align="right">1.0E+9</td><td align="right">1.0E+6</td><td align="right">1.0E+3</td><td align="right">1.0</td><td align="right">0.0010</td><td align="right">0.00010</td><td align="right">0.000010</td><td align="right">0.0000010</td><td align="right">1.0E-7</td><td align="right">1.0E-8</td><td align="right">1.0E-9</td><td align="right">1.0E-12</td><td align="right">1.0E-15</td><td align="right">1.0E-18</td><td align="right">1.0E-21</td><td align="right">1.0E-24</td><td align="right">1.0E-27</td><td align="right">1.0E-30</td></tr>
083     * <tr><td>MILLIHERTZ</td><td align="right">1.0E+21</td><td align="right">1.0E+18</td><td align="right">1.0E+15</td><td align="right">1.0E+12</td><td align="right">1.0E+9</td><td align="right">1.0E+6</td><td align="right">1.0E+3</td><td align="right">1.0</td><td align="right">0.10</td><td align="right">0.010</td><td align="right">0.0010</td><td align="right">0.00010</td><td align="right">0.000010</td><td align="right">0.0000010</td><td align="right">1.0E-9</td><td align="right">1.0E-12</td><td align="right">1.0E-15</td><td align="right">1.0E-18</td><td align="right">1.0E-21</td><td align="right">1.0E-24</td><td align="right">1.0E-27</td></tr>
084     * <tr><td>CENTIHERTZ</td><td align="right">1.0E+22</td><td align="right">1.0E+19</td><td align="right">1.0E+16</td><td align="right">1.0E+13</td><td align="right">1.0E+10</td><td align="right">1.0E+7</td><td align="right">1.0E+4</td><td align="right">10</td><td align="right">1.0</td><td align="right">0.10</td><td align="right">0.010</td><td align="right">0.0010</td><td align="right">0.00010</td><td align="right">0.000010</td><td align="right">1.0E-8</td><td align="right">1.0E-11</td><td align="right">1.0E-14</td><td align="right">1.0E-17</td><td align="right">1.0E-20</td><td align="right">1.0E-23</td><td align="right">1.0E-26</td></tr>
085     * <tr><td>DECIHERTZ</td><td align="right">1.0E+23</td><td align="right">1.0E+20</td><td align="right">1.0E+17</td><td align="right">1.0E+14</td><td align="right">1.0E+11</td><td align="right">1.0E+8</td><td align="right">1.0E+5</td><td align="right">1.0E+2</td><td align="right">10</td><td align="right">1.0</td><td align="right">0.10</td><td align="right">0.010</td><td align="right">0.0010</td><td align="right">0.00010</td><td align="right">1.0E-7</td><td align="right">1.0E-10</td><td align="right">1.0E-13</td><td align="right">1.0E-16</td><td align="right">1.0E-19</td><td align="right">1.0E-22</td><td align="right">1.0E-25</td></tr>
086     * <tr><td>HERTZ</td><td align="right">1.0E+24</td><td align="right">1.0E+21</td><td align="right">1.0E+18</td><td align="right">1.0E+15</td><td align="right">1.0E+12</td><td align="right">1.0E+9</td><td align="right">1.0E+6</td><td align="right">1.0E+3</td><td align="right">1.0E+2</td><td align="right">10</td><td align="right">1.0</td><td align="right">0.10</td><td align="right">0.010</td><td align="right">0.0010</td><td align="right">0.0000010</td><td align="right">1.0E-9</td><td align="right">1.0E-12</td><td align="right">1.0E-15</td><td align="right">1.0E-18</td><td align="right">1.0E-21</td><td align="right">1.0E-24</td></tr>
087     * <tr><td>DECAHERTZ</td><td align="right">1.0E+25</td><td align="right">1.0E+22</td><td align="right">1.0E+19</td><td align="right">1.0E+16</td><td align="right">1.0E+13</td><td align="right">1.0E+10</td><td align="right">1.0E+7</td><td align="right">1.0E+4</td><td align="right">1.0E+3</td><td align="right">1.0E+2</td><td align="right">10</td><td align="right">1.0</td><td align="right">0.10</td><td align="right">0.010</td><td align="right">0.000010</td><td align="right">1.0E-8</td><td align="right">1.0E-11</td><td align="right">1.0E-14</td><td align="right">1.0E-17</td><td align="right">1.0E-20</td><td align="right">1.0E-23</td></tr>
088     * <tr><td>HECTOHERTZ</td><td align="right">1.0E+26</td><td align="right">1.0E+23</td><td align="right">1.0E+20</td><td align="right">1.0E+17</td><td align="right">1.0E+14</td><td align="right">1.0E+11</td><td align="right">1.0E+8</td><td align="right">1.0E+5</td><td align="right">1.0E+4</td><td align="right">1.0E+3</td><td align="right">1.0E+2</td><td align="right">10</td><td align="right">1.0</td><td align="right">0.10</td><td align="right">0.00010</td><td align="right">1.0E-7</td><td align="right">1.0E-10</td><td align="right">1.0E-13</td><td align="right">1.0E-16</td><td align="right">1.0E-19</td><td align="right">1.0E-22</td></tr>
089     * <tr><td>KILOHERTZ</td><td align="right">1.0E+27</td><td align="right">1.0E+24</td><td align="right">1.0E+21</td><td align="right">1.0E+18</td><td align="right">1.0E+15</td><td align="right">1.0E+12</td><td align="right">1.0E+9</td><td align="right">1.0E+6</td><td align="right">1.0E+5</td><td align="right">1.0E+4</td><td align="right">1.0E+3</td><td align="right">1.0E+2</td><td align="right">10</td><td align="right">1.0</td><td align="right">0.0010</td><td align="right">0.0000010</td><td align="right">1.0E-9</td><td align="right">1.0E-12</td><td align="right">1.0E-15</td><td align="right">1.0E-18</td><td align="right">1.0E-21</td></tr>
090     * <tr><td>MEGAHERTZ</td><td align="right">1.0E+30</td><td align="right">1.0E+27</td><td align="right">1.0E+24</td><td align="right">1.0E+21</td><td align="right">1.0E+18</td><td align="right">1.0E+15</td><td align="right">1.0E+12</td><td align="right">1.0E+9</td><td align="right">1.0E+8</td><td align="right">1.0E+7</td><td align="right">1.0E+6</td><td align="right">1.0E+5</td><td align="right">1.0E+4</td><td align="right">1.0E+3</td><td align="right">1.0</td><td align="right">0.0010</td><td align="right">0.0000010</td><td align="right">1.0E-9</td><td align="right">1.0E-12</td><td align="right">1.0E-15</td><td align="right">1.0E-18</td></tr>
091     * <tr><td>GIGAHERTZ</td><td align="right">1.0E+33</td><td align="right">1.0E+30</td><td align="right">1.0E+27</td><td align="right">1.0E+24</td><td align="right">1.0E+21</td><td align="right">1.0E+18</td><td align="right">1.0E+15</td><td align="right">1.0E+12</td><td align="right">1.0E+11</td><td align="right">1.0E+10</td><td align="right">1.0E+9</td><td align="right">1.0E+8</td><td align="right">1.0E+7</td><td align="right">1.0E+6</td><td align="right">1.0E+3</td><td align="right">1.0</td><td align="right">0.0010</td><td align="right">0.0000010</td><td align="right">1.0E-9</td><td align="right">1.0E-12</td><td align="right">1.0E-15</td></tr>
092     * <tr><td>TERAHERTZ</td><td align="right">1.0E+36</td><td align="right">1.0E+33</td><td align="right">1.0E+30</td><td align="right">1.0E+27</td><td align="right">1.0E+24</td><td align="right">1.0E+21</td><td align="right">1.0E+18</td><td align="right">1.0E+15</td><td align="right">1.0E+14</td><td align="right">1.0E+13</td><td align="right">1.0E+12</td><td align="right">1.0E+11</td><td align="right">1.0E+10</td><td align="right">1.0E+9</td><td align="right">1.0E+6</td><td align="right">1.0E+3</td><td align="right">1.0</td><td align="right">0.0010</td><td align="right">0.0000010</td><td align="right">1.0E-9</td><td align="right">1.0E-12</td></tr>
093     * <tr><td>PETAHERTZ</td><td align="right">1.0E+39</td><td align="right">1.0E+36</td><td align="right">1.0E+33</td><td align="right">1.0E+30</td><td align="right">1.0E+27</td><td align="right">1.0E+24</td><td align="right">1.0E+21</td><td align="right">1.0E+18</td><td align="right">1.0E+17</td><td align="right">1.0E+16</td><td align="right">1.0E+15</td><td align="right">1.0E+14</td><td align="right">1.0E+13</td><td align="right">1.0E+12</td><td align="right">1.0E+9</td><td align="right">1.0E+6</td><td align="right">1.0E+3</td><td align="right">1.0</td><td align="right">0.0010</td><td align="right">0.0000010</td><td align="right">1.0E-9</td></tr>
094     * <tr><td>ETAHERTZ</td><td align="right">1.0E+42</td><td align="right">1.0E+39</td><td align="right">1.0E+36</td><td align="right">1.0E+33</td><td align="right">1.0E+30</td><td align="right">1.0E+27</td><td align="right">1.0E+24</td><td align="right">1.0E+21</td><td align="right">1.0E+20</td><td align="right">1.0E+19</td><td align="right">1.0E+18</td><td align="right">1.0E+17</td><td align="right">1.0E+16</td><td align="right">1.0E+15</td><td align="right">1.0E+12</td><td align="right">1.0E+9</td><td align="right">1.0E+6</td><td align="right">1.0E+3</td><td align="right">1.0</td><td align="right">0.0010</td><td align="right">0.0000010</td></tr>
095     * <tr><td>ZETTAHERTZ</td><td align="right">1.0E+45</td><td align="right">1.0E+42</td><td align="right">1.0E+39</td><td align="right">1.0E+36</td><td align="right">1.0E+33</td><td align="right">1.0E+30</td><td align="right">1.0E+27</td><td align="right">1.0E+24</td><td align="right">1.0E+23</td><td align="right">1.0E+22</td><td align="right">1.0E+21</td><td align="right">1.0E+20</td><td align="right">1.0E+19</td><td align="right">1.0E+18</td><td align="right">1.0E+15</td><td align="right">1.0E+12</td><td align="right">1.0E+9</td><td align="right">1.0E+6</td><td align="right">1.0E+3</td><td align="right">1.0</td><td align="right">0.0010</td></tr>
096     * <tr><td>YOTTAHERTZ</td><td align="right">1.0E+48</td><td align="right">1.0E+45</td><td align="right">1.0E+42</td><td align="right">1.0E+39</td><td align="right">1.0E+36</td><td align="right">1.0E+33</td><td align="right">1.0E+30</td><td align="right">1.0E+27</td><td align="right">1.0E+26</td><td align="right">1.0E+25</td><td align="right">1.0E+24</td><td align="right">1.0E+23</td><td align="right">1.0E+22</td><td align="right">1.0E+21</td><td align="right">1.0E+18</td><td align="right">1.0E+15</td><td align="right">1.0E+12</td><td align="right">1.0E+9</td><td align="right">1.0E+6</td><td align="right">1.0E+3</td><td align="right">1.0</td></tr>
097     * </table>
098     * <sup><b>3</b></sup>This table was generated from the
099     * <tt>convertTo</tt> method of this class.<br/>
100     * </p>
101     * <p>
102     * <b>Version Info:</b>
103     * <table style="margin-left:2em">
104     *   <tr><td>$Revision: 1586 $</td></tr>
105     *   <tr><td>$Date: 2008-10-01 10:38:49 -0600 (Wed, 01 Oct 2008) $</td></tr>
106     *   <tr><td>$Author: dharland $</td></tr>
107     * </table></p>
108     *
109     * @author David M. Harland
110     * @since 2006-03-31
111     */
112    public enum FrequencyUnits
113      implements Symbolic
114    {
115      /** 10<sup>-24</sup> cycles per second. */
116      YOCTOHERTZ("1e-24", "yHz", -24),
117    
118      /** 10<sup>-21</sup> cycles per second. */
119      ZEPTOHERTZ("1e-21", "zHz", -21),
120    
121      /** 10<sup>-18</sup> cycles per second. */
122      ATTOHERTZ("1e-18", "aHz", -18),
123    
124      /** 10<sup>-15</sup> cycles per second. */
125      FEMTOHERTZ("1e-15", "fHz", -15),
126    
127      /** 10<sup>-12</sup> cycles per second. */
128      PICOHERTZ("1e-12", "pHz", -12),
129    
130      /** 10<sup>-9</sup> cycles per second. */
131      NANOHERTZ("1e-9", "nHz", -9),
132    
133      /** 10<sup>-6</sup> cycles per second. */
134      MICROHERTZ("1e-6", '\u00B5'+"Hz", -6),
135    
136      /** 0.001 cycles per second. */
137      MILLIHERTZ("1e-3", "mHz", -3),
138    
139      /** 0.01 cycles per second. */
140      CENTIHERTZ("1e-2", "cHz", -2),
141    
142      /** 0.1 cycles per second. */
143      DECIHERTZ("1e-1", "dHz", -1),
144    
145      /** 1 cycle per second. */
146      HERTZ("1e0", "Hz", 0),
147    
148      /** 10 cycles per second. */
149      DECAHERTZ("1e1", "daHz", 1),
150    
151      /** 100 cycles per second. */
152      HECTOHERTZ("1e2", "hHz", 2),
153    
154      /** 1,000 cycles per second. */
155      KILOHERTZ("1e3", "kHz", 3),
156    
157      /** 10<sup>6</sup> cycles per second. */
158      MEGAHERTZ("1e6", "MHz", 6),
159    
160      /** 10<sup>9</sup> cycles per second. */
161      GIGAHERTZ("1e9", "GHz", 9),
162    
163      /** 10<sup>12</sup> cycles per second. */
164      TERAHERTZ("1e12", "THz", 12),
165    
166      /** 10<sup>15</sup> cycles per second. */
167      PETAHERTZ("1e15", "PHz", 15),
168    
169      /** 10<sup>18</sup> cycles per second. */
170      ETAHERTZ("1e18", "EHz", 18),
171    
172      /** 10<sup>21</sup> cycles per second. */
173      ZETTAHERTZ("1e21", "ZHz", 21),
174    
175      /** 10<sup>24</sup> cycles per second. */
176      YOTTAHERTZ("1e24", "YHz", 24);
177    
178      private static final int PRECISION = MC_FINAL_CALC.getPrecision(); 
179    
180      private BigDecimal hertz;
181      private String     symbol;
182      private int        power;
183    
184      private FrequencyUnits(String hertz, String symbol, int power)
185      {
186        this.symbol = symbol;
187        this.power  = power;
188        this.hertz  = new BigDecimal(hertz);
189        
190        //It turns out that the PRECISION constant is zero when we're
191        //in this constructor, so we make the call directly.
192        //(See http://forums.java.net/jive/thread.jspa?threadID=40585&tstart=0)
193        this.hertz = this.hertz.setScale(MC_FINAL_CALC.getPrecision(),
194                                         RoundingMode.HALF_UP);
195      }
196      
197      /** Returns <i>true</i> -- these symbols <i>are</i> case sensitive. */
198      public boolean symbolsAreCaseSensitive()  { return false; }
199    
200      /**
201       * Returns the symbol for this unit.
202       * For example, the symbol for {@code Hertz} is <i>Hz</i>.
203       *
204       * @return the symbol for this unit.
205       */
206      public String getSymbol()
207      {
208        return symbol;
209      }
210    
211      /**
212       * Returns the number of cycles per second for this unit.
213       *
214       * @return the number of hertz in this unit.
215       */
216      public BigDecimal toHertz()
217      {
218        return hertz;
219      }
220    
221      /**
222       * Returns a factor for converting from this unit to {@code otherUnits}.
223       *
224       * @param otherUnits the unit to which conversion is desired.
225       *
226       * @return a factor for converting from this unit to {@code otherUnits}.
227       */
228      public BigDecimal toUnits(FrequencyUnits otherUnits)
229      {
230        return convertTo(otherUnits, BigDecimal.ONE);
231      }
232    
233      /**
234       * Non-public method for use by this and other classes in pkg.
235       * Tries to keep all calcs in BigDecimal form, but if that fails,
236       * reverts to java primitives.
237       */
238      BigDecimal convertTo(FrequencyUnits otherUnits, BigDecimal value)
239      {
240        BigDecimal answer = value;
241    
242        //Convert only if we have different units
243        if (!otherUnits.equals(this))
244        {
245          try  //to use BigDecimal, for better accuracy, but...
246          {
247            if (value.scale() < PRECISION)
248              value = value.setScale(PRECISION);
249            
250            BigDecimal ratio = this.hertz.divide(otherUnits.hertz,
251                                                 MC_INTERM_CALCS);
252            answer = value.multiply(ratio, MC_FINAL_CALC);
253          }
254          catch (ArithmeticException ex)
255          {
256            //...if it fails, use java primitives
257            double ratio =       this.hertz.doubleValue() /
258                           otherUnits.hertz.doubleValue();
259    
260            answer = BigDecimal.valueOf(value.doubleValue() * ratio);
261          }
262        }
263    
264        return answer.round(MC_FINAL_CALC);
265      }
266    
267      /**
268       * Returns a default unit of frequency.
269       * @return a default unit of frequency.
270       */
271      public static FrequencyUnits getDefault()
272      {
273        return HERTZ;
274      }
275    
276      /**
277       * Returns the element that represents the largest number of Hertz.
278       * @return the element that represents the largest number of Hertz.
279       */
280      public static FrequencyUnits getLargest()
281      {
282        return FrequencyUnits.YOTTAHERTZ;
283      }
284    
285      /**
286       * Returns the element that represents the smallest number of Hertz.
287       * @return the element that represents the smallest number of Hertz.
288       */
289      public static FrequencyUnits getSmallest()
290      {
291        return FrequencyUnits.YOCTOHERTZ;
292      }
293    
294      /**
295       * Returns the units that corresponds to
296       * 1.0 * 10<sup>{@code powerOfTen}</sup> Hz.
297       * <p>
298       * If there is no units with the exact {@code powerOfTen} Hz,
299       * the largest units whose power is less than {@code powerOfTen}
300       * will be returned.  If {@code powerOfTen} is less than that of the
301       * smallest units, the smallest units will be returned.
302       *
303       * @return the units that corresponds to
304       *         1.0 * 10<sup>{@code powerOfTen}</sup> Hz.
305       */
306      public static FrequencyUnits getForPower(int powerOfTen)
307      {
308        FrequencyUnits result = getSmallest();
309    
310        //This loop relies on the fact that values() presents elements in
311        //declared order, and that our declared order is from smallest to largest.
312        for (FrequencyUnits units : values())
313        {
314          if (powerOfTen < units.power)
315            break;
316    
317          result = units;
318        }
319    
320        return result;
321      }
322    
323      /**
324       * Similar to {@link #getForPower(int)}, but the returned units will have
325       * a power that is evenly divisible by three.
326       */
327      public static FrequencyUnits getForMultipleOfThreePower(int powerOfTen)
328      {
329        FrequencyUnits result = getSmallest();
330    
331        //This loop relies on the fact that values() presents elements in
332        //declared order, and that our declared order is from smallest to largest.
333        for (FrequencyUnits units : values())
334        {
335          if ((units.power % 3) != 0)
336            continue;
337    
338          if (powerOfTen < units.power)
339            break;
340    
341          result = units;
342        }
343    
344        return result;
345      }
346    
347      /**
348       * Returns a text representation of this enumeration constant.
349       * @return a text representation of this enumeration constant.
350       */
351      public String toString()
352      {
353        return EnumerationUtility.getSharedInstance().enumToString(this);
354      }
355    
356      /**
357       * Returns the frequency units represented by {@code text}.
358       * <p>
359       * Leading and trailing whitespace is first stripped from {@code text}.
360       * A case-insensitive comparison against the {@code name} and
361       * {@code toString} methods of each constant in the enumeration is then
362       * performed, while a case-<i>sensitive</i> comparison is done againt the
363       * {@code getSymbol} method.  If no match is found, <i>null</i>
364       * is returned.  The comparison of the symbol needs to be case-sensitive
365       * because of units such as millihertz (mHz) and megahertz (MHz).</p>
366       *
367       * @param text a text representation of a unit of frequency.
368       *
369       * @return the frequency units represented by {@code text}.
370       */
371      public static FrequencyUnits fromString(String text)
372      {
373        FrequencyUnits result = null;
374    
375        //Remove leading & trailing whitespace from text and handle null
376        text = StringUtil.getInstance().normalizeString(text);
377    
378        //Loop through enumeration constants of input class
379        for (FrequencyUnits element : values())
380        {
381          //Try to match against standard name and toString methods
382          if (text.equalsIgnoreCase(element.name())     ||
383              text.equalsIgnoreCase(element.toString()) ||
384              text.equals          (element.getSymbol()))
385          {
386            result = element;
387            break;
388          }
389        }
390    
391        return result;
392      }
393    
394      //Here for testing only
395      /*
396      private static String toHtmlTable()
397      {
398        StringBuilder table = new StringBuilder();
399    
400        //Column headers
401        table.append(" * <table border=\"1\" cellspacing=\"0\">\n");
402        table.append(" * <tr BGCOLOR=\"#EEEEFF\"><th> </th>");
403        for (FrequencyUnits u : FrequencyUnits.values())
404          table.append("<th>").append(u.getSymbol()).append("</th>");
405        table.append("</tr>\n");
406    
407        //Data rows
408        for (FrequencyUnits from : FrequencyUnits.values())
409        {
410          table.append(" * <tr><td>").append(from.name()).append("</td>");
411    
412          for (FrequencyUnits to : FrequencyUnits.values())
413            table.append("<td align=\"right\">").append(from.convertAccuratelyTo(to)).append("</td>");
414    
415          table.append("</tr>\n");
416        }
417    
418        //End table
419        table.append(" * </table>");
420    
421        return table.toString();
422      }
423    
424      public static void main(String[] args)
425      {
426        String htmlTable = FrequencyUnits.toHtmlTable();
427    
428        System.out.println(htmlTable);
429      }
430      */
431    }