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