Guest User

Maths by S.Devulder

a guest
Apr 7th, 2016
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 10.90 KB | None | 0 0
  1. public class FP extends Number implements Comparable<FP> {
  2.     // http://www.quinapalus.com/efunc.html
  3.    
  4.    
  5.     private static final long serialVersionUID = 1L;
  6.     byte sign, exp;
  7.     long mantissa;
  8.  
  9.     static final int BITS = 7;
  10.  
  11.     static long ONE_MSK = 1l<<BITS;
  12.    
  13.     static FP ZERO = new FP(0, 0, 0);
  14.     static FP LN2 = new FP(1, -1, (long) (Math.log(2) * ONE_MSK * 2 + .5));
  15.     static FP ONE = new FP(1, 0, 1 << BITS);
  16.     static FP SQRT2 = new FP(1, 0, (long) (Math.sqrt(2) * ONE_MSK + .5));
  17.     static FP TWO = new FP(1, 1, 1 << BITS);
  18.     static FP LN10 = new FP(1, 1, (long) (Math.log(10) * ONE_MSK/2 + .5));
  19.     static FP E = new FP(1, 1, (long) (Math.exp(1) * ONE_MSK/2 + .5));
  20.     static FP PI = new FP(1, 1, (long) (Math.PI * ONE_MSK/2 + .5));
  21.     static FP TEN = new FP(1, 3, 10 << (BITS - 3));
  22.     static FP MAX = new FP(1, 127, ONE_MSK*2 - 1);
  23.  
  24.     public static void main(String[] args) {
  25.         System.out.println("LN2=" + LN2);
  26.         System.out.println("ONE=" + ONE);
  27.         System.out.println("SQRT2=" + SQRT2);
  28.         System.out.println("TWO=" + TWO);
  29.         System.out.println("LN10=" + LN10);
  30.         System.out.println("PI=" + PI);
  31.         System.out.println("TEN=" + TEN);
  32.         System.out.println("MAX=" + MAX);
  33.         System.out.println("ONE+SQRT2=" + ONE.add(SQRT2));
  34.         System.out.println("ONE-SQRT2=" + ONE.sub(SQRT2));
  35.         System.out.println("SQRT2-SQRT2=" + SQRT2.sub(SQRT2));
  36.         System.out.println("SQRT2*SQRT2=" + SQRT2.mul(SQRT2));
  37.         System.out.println("SQRT2/SQRT2=" + SQRT2.div(SQRT2));
  38.         System.out.println("ONE/MAX=" + ONE.div(MAX));
  39.         System.out.println("parse1=" + new FP("-314.1592653589E-2"));
  40.         System.out.println("parse2=" + new FP("3.141592653589"));
  41.  
  42.         System.out.println("ln(2)=" + TWO.ln());
  43.         System.out.println("ln(10)=" + TEN.ln());
  44.  
  45.         System.out.println("log10(2)=" + TWO.log10());
  46.         System.out.println("log10(10)=" + TEN.log10());
  47.        
  48.         System.out.println("sqrt(2)=" + TWO.sqrt());
  49.         System.out.println("sqrt(10)=" + TEN.sqrt());
  50.  
  51.         System.out.println("exp(-2)=" + TWO.neg().exp());
  52.         System.out.println("exp(-1)=" + ONE.neg().exp());
  53.         System.out.println("exp(0)=" + ZERO.exp());
  54.         System.out.println("exp(1)=" + ONE.exp());
  55.         System.out.println("exp(2)=" + TWO.exp());
  56.         System.out.println("exp(ln2)=" + LN2.exp());
  57.         System.out.println("exp(ln10)=" + LN10.exp());
  58.     }
  59.  
  60.     FP(int sign, int exp, long mantissa) {
  61.         build(sign, exp, mantissa);
  62.     }
  63.    
  64.     protected int sign() {
  65.         return sign;
  66.     }
  67.    
  68.     protected int exponent() {
  69.         return exp;
  70.     }
  71.    
  72.     protected long mantissa() {
  73.         return mantissa;
  74.     }
  75.  
  76.     public FP(double d) {
  77.         int sgn = d < 0 ? -1 : d > 0 ? 1 : 0;
  78.         int exp = Math.getExponent(d);
  79.         int man = (int) Math.scalb(sgn < 0 ? -d : d, BITS - exp);
  80.         build(man == 0 ? 0 : sgn, exp, man);
  81.     }
  82.  
  83.     public FP(String s_) {
  84.         int i = 0;
  85.         char[] s = s_.toCharArray();
  86.  
  87.         // read sign
  88.         int sgn = 1;
  89.         while (i < s.length && (s[i] == '-' || s[i] == '+')) {
  90.             if (s[i++] == '-')
  91.                 sgn = -sgn;
  92.         }
  93.  
  94.         // read int part
  95.         FP v = ZERO;
  96.         while (i < s.length && s[i] >= '0' && s[i] <= '9') {
  97.             v = v.mul(TEN).add(s[i++] - '0');
  98.         }
  99.  
  100.         // read decimal
  101.         if (i < s.length && s[i] == '.') {
  102.             FP div = ONE;
  103.             ++i;
  104.             while (i < s.length && s[i] >= '0' && s[i] <= '9') {
  105.                 div = div.div(TEN);
  106.                 v = v.add(div.mul(s[i++] - '0'));
  107.             }
  108.         }
  109.  
  110.         // read exponent
  111.         if (i < s.length && (s[i] == 'e' || s[i] == 'E')) {
  112.             ++i;
  113.  
  114.             int sgn2 = 1;
  115.             while (i < s.length && (s[i] == '-' || s[i] == '+')) {
  116.                 if (s[i++] == '-')
  117.                     sgn2 = -sgn2;
  118.             }
  119.  
  120.             FP e = ONE;
  121.             while (i < s.length && s[i] >= '0' && s[i] <= '9') {
  122.                 e = e.pow(10).mul(pow_tab[s[i++]-'0']);
  123.             }
  124.  
  125.             v = sgn2 < 0 ? v.div(e) : v.mul(e);
  126.         }
  127.  
  128.         if (sgn < 0)
  129.             v = v.neg();
  130.  
  131.         build(v.sign(), v.exponent(), v.mantissa());
  132.     }
  133.     static FP[] pow_tab = {ONE, TEN, TEN.square(), TEN.pow(3), TEN.pow(4), TEN.pow(5), TEN.pow(6), TEN.pow(7), TEN.pow(8), TEN.pow(9)};
  134.  
  135.     protected FP build(int sign, int exp, long mantissa) {
  136.         this.sign = (byte) sign;
  137.         this.exp = (byte) exp;
  138.         this.mantissa = mantissa & (ONE_MSK*2 - 1);
  139.         if(sign!=0 && (this.mantissa & ONE_MSK)==0) throw new RuntimeException("Bad mantissa " + Long.toHexString(this.mantissa));
  140.         return this;
  141.     }
  142.  
  143.     @Override
  144.     public boolean equals(Object obj) {
  145.         return obj instanceof FP && compareTo((FP) obj) == 0;
  146.     }
  147.  
  148.     @Override
  149.     public int hashCode() {
  150.         if (sign == 0)
  151.             return 0;
  152.         return (int) ((sign * 31 + mantissa) * 31 + exp);
  153.     }
  154.  
  155.     @Override
  156.     public double doubleValue() {
  157.         if (sign() == 0)
  158.             return 0;
  159.         double t = mantissa() * Math.pow(2, exponent() - BITS);
  160.         return sign() < 0 ? -t : t;
  161.     }
  162.  
  163.     @Override
  164.     public float floatValue() {
  165.         return (float) doubleValue();
  166.     }
  167.  
  168.     @Override
  169.     public int intValue() {
  170.         return (int) longValue();
  171.     }
  172.  
  173.     @Override
  174.     public long longValue() {
  175.         int sgn = sign();
  176.         if (sgn == 0)
  177.             return 0;
  178.         long val = mantissa() >>> (BITS - exponent());
  179.         return sgn < 0 ? -val : val;
  180.     }
  181.  
  182.     public FP floor() {
  183.         int exp = exponent();
  184.         if (exp < 0)
  185.             return ZERO;
  186.         if (exp > BITS)
  187.             return this;
  188.         long m = (2l << BITS) - ((1l << BITS) >>> exp);
  189.         return new FP(sign(), exp, mantissa() & m);
  190.     }
  191.  
  192.     static FP PRECISION;
  193.  
  194.     static {
  195.         FP x = ONE, y = new FP(1, -BITS, 1 << BITS);
  196.         while (x.compareTo(y) > 0) {
  197.             PRECISION = x;
  198.             x = x.div(TEN);
  199.         }
  200.     }
  201.  
  202.     public String toString() {
  203.         // return Double.toString(doubleValue());
  204.  
  205.         // http://stackoverflow.com/questions/2302969/how-to-implement-char-ftoafloat-num-without-sprintf-library-function-i
  206.         if (sign() == 0)
  207.             return "0";
  208.         StringBuilder sb = new StringBuilder();
  209.  
  210.         boolean neg = sign() < 0;
  211.         FP x = this.abs();
  212.         // if(x.mantissa!=0xFFFF) ++x.mantissa;
  213.         int m = 0, m1 = 0;
  214.         // while(TEN.pow(m+1).compareTo(x)<=0) ++m;
  215.         m = x.log10().add(PRECISION).intValue();
  216.         boolean useExp = (m >= 5 || (neg && m >= 3) || m <= -5);
  217.         if (neg)
  218.             sb.append('-');
  219.         // set up for scientific notation
  220.         if (useExp) {
  221.             if (m < 0)
  222.                 --m;
  223.             x = x.mul(TEN.pow(-m));
  224.             m1 = m;
  225.             m = 0;
  226.         }
  227.         if (m < 1.0) {
  228.             m = 0;
  229.         }
  230.         // convert the number
  231.         while (x.compareTo(PRECISION) > 0 || m >= 0) {
  232.             FP weight = TEN.pow(m);
  233.             if (weight.tst() > 0) {
  234.                 int digit = x.div(weight).intValue();
  235.                 x = x.sub(weight.mul(digit));
  236.                 sb.append((char) ('0' + digit));
  237.             }
  238.             if (m == 0 && x.tst() > 0)
  239.                 sb.append('.');
  240.             m--;
  241.         }
  242.         if (useExp) {
  243.             // convert the exponent
  244.             sb.append('e');
  245.             if (m1 > 0) {
  246.                 sb.append('+');
  247.             } else {
  248.                 sb.append('-');
  249.                 m1 = -m1;
  250.             }
  251.             if (m1 > 10) {
  252.                 sb.append((char) ('0' + m1 / 10));
  253.                 m1 = m1 % 10;
  254.             }
  255.             sb.append((char) ('0' + m1));
  256.         }
  257.         return sb.toString();
  258.     };
  259.  
  260.     public FP neg() {
  261.         return new FP(-sign(), exponent(), mantissa());
  262.     }
  263.  
  264.     public FP abs() {
  265.         return new FP(sign() == 0 ? 0 : 1, exponent(), mantissa());
  266.     }
  267.  
  268.     public FP copySign(FP other) {
  269.         return new FP(other.sign(), exponent(), mantissa());
  270.     }
  271.  
  272.     public int tst() {
  273.         return sign();
  274.     }
  275.  
  276.     public int compareTo(FP other) {
  277.         int d = this.sign() - other.sign();
  278.         if (d != 0) {
  279.             return d;
  280.         }
  281.         if (this.sign() == 0)
  282.             return 0;
  283.         d = this.exponent() - other.exponent();
  284.         if (d != 0)
  285.             return d;
  286.         d = (int) (this.mantissa() - other.mantissa());
  287.         return d;
  288.     }
  289.  
  290.     public FP mul(FP other) {
  291.         if ((this.sign() & other.sign()) == 0)
  292.             return ZERO;
  293.         int sign = (this.sign() ^ other.sign()) | 1;
  294.         int exp = this.exponent() + other.exponent();
  295.         long mant = (this.mantissa() * other.mantissa()) >>> BITS;
  296.         if ((mant & (2l << BITS)) != 0) {
  297.             mant >>>= 1;
  298.             ++exp;
  299.         }
  300.         return new FP(mant==0?0:sign, exp, mant);
  301.     }
  302.  
  303.     public FP mul(double v) {
  304.         return mul(new FP(v));
  305.     }
  306.  
  307.     public FP square() {
  308.         return mul(this);
  309.     }
  310.  
  311.     public FP pow(int n) {
  312.         boolean neg = n < 0;
  313.         if (neg)
  314.             n = -n;
  315.         FP x = this, y = ONE;
  316.         while (n != 0) {
  317.             if ((n & 1) != 0) {
  318.                 y = y.mul(x);
  319.             }
  320.             x = x.square();
  321.             n >>>= 1;
  322.         }
  323.         return neg ? y.inv() : y;
  324.     }
  325.  
  326.     public FP div(FP other) {
  327.         if (other.sign() == 0)
  328.             return MAX.copySign(other);
  329.         if (this.sign() == 0)
  330.             return ZERO;
  331.         int sign = (this.sign() ^ other.sign()) | 1;
  332.         int exp = this.exponent() - other.exponent();
  333.         long mant = (this.mantissa() << (1 + BITS)) / other.mantissa();
  334.         if ((mant & (2l << BITS)) != 0) {
  335.             mant >>>= 1;
  336.         } else {
  337.             --exp;
  338.         }
  339.         return new FP(sign, exp, mant);
  340.     }
  341.  
  342.     public FP inv() {
  343.         return ONE.div(this);
  344.     }
  345.  
  346.     public FP sub(FP other) {
  347.         return add(other.neg());
  348.     }
  349.  
  350.     public FP add(FP other) {
  351.         if (sign() == 0)
  352.             return other;
  353.         if (other.sign() == 0)
  354.             return this;
  355.  
  356.         FP small = this;
  357.         FP big = other;
  358.         if (small.exponent() == big.exponent()) {
  359.             if (small.mantissa() > big.mantissa()) {
  360.                 small = other;
  361.                 big = this;
  362.             }
  363.         } else if (small.exponent() > big.exponent()) {
  364.             small = other;
  365.             big = this;
  366.         }
  367.         int exp = big.exponent();
  368.         long mant = big.mantissa();
  369.         long delta = small.mantissa() >>> (big.exponent() - small.exponent());
  370.         if (big.sign() == small.sign()) {
  371.             mant += delta;
  372.             if ((mant & (2l << BITS)) != 0) {
  373.                 mant >>>= 1;
  374.                 ++exp;
  375.             }
  376.         } else {
  377.             mant -= delta;
  378.             if (mant == 0)
  379.                 return ZERO;
  380.             while ((mant & (1l << BITS)) == 0) {
  381.                 mant <<= 1;
  382.                 --exp;
  383.             }
  384.         }
  385.         return new FP(big.sign(), exp, mant);
  386.     }
  387.  
  388.     protected FP add(double v) {
  389.         return add(new FP(v));
  390.     }
  391.  
  392.     static protected FP[] ln = { new FP(8.690628917915396e-06), new FP(0.9992996219306662), new FP(-0.4907434587925273), new FP(0.2867076984634543), new FP(-0.1332213692732176),
  393.             new FP(0.03110469698575859) };
  394.  
  395.     public FP ln() {
  396.         if (sign() <= 0)
  397.             return MAX.neg();
  398.         FP x = new FP(1, 0, mantissa()).sub(ONE), y = ZERO;
  399.         for (int i = ln.length; --i >= 0;)
  400.             y = y.mul(x).add(ln[i]);
  401.         int exp = this.exponent() < 0 ? -this.exponent() : this.exponent();
  402.         while (exp > 0) {
  403.             y = y.add(LN2);
  404.             --exp;
  405.         }
  406.         if (this.exponent() < 0)
  407.             y = y.neg();
  408.         return y;
  409.     }
  410.  
  411.     public FP log10() {
  412.         return ln().div(LN10);
  413.     }
  414.  
  415.     public FP sqrt() {
  416.         if (sign() <= 0)
  417.             return ZERO;
  418.  
  419.         long op = mantissa() << BITS;
  420.         long one = 1l << (BITS + BITS);
  421.         long res = 0;
  422.         while (one != 0) {
  423.             if (op >= res + one) {
  424.                 op -= res + one;
  425.                 res += one << 1;
  426.             }
  427.             res >>>= 1;
  428.             one >>>= 2;
  429.         }
  430.         /* Do arithmetic rounding to nearest integer */
  431.         if (op > res)
  432.         {
  433.             res++;
  434.         }
  435.  
  436.         FP x = new FP(1, this.exponent() >> 1, res);
  437.         if ((this.exponent() & 1) != 0)
  438.             x = x.mul(SQRT2);
  439.         return x;
  440.     }
  441.    
  442.     public FP exp() {
  443.         //exp(2^x * y) = exp(y)^(2^x) = exp(2^0) * exp(2^-1)
  444.        
  445.         if(sign()==0) return ONE;
  446.        
  447.         // exp(y)
  448.         FP x = ONE, y = E;
  449.         long m = mantissa(), msk=ONE_MSK;
  450.         while(m!=0) {
  451.             if((m & msk)!=0) {x = x.mul(y); m^=msk;}
  452.             y = y.sqrt(); msk>>=1;
  453.             if(ONE.equals(y)) break;
  454.         }
  455.        
  456.         // exp(2^exponent)
  457.         int exp = exponent();
  458.         while(exp>0) {x = x.square(); --exp; if(MAX.compareTo(x)==0) break;}
  459.         while(exp<0) {x = x.sqrt(); ++exp; if(ONE.compareTo(x)==0) break;}
  460.        
  461.         return sign()<0?x.inv():x;
  462.     }
  463. }
Advertisement
Add Comment
Please, Sign In to add comment