Ranides Atterwim %!s(int64=12) %!d(string=hai) anos
pai
achega
7259b5ec13

+ 4 - 4
src/main/java/net/ranides/assira/collection/map/CompositeKey.java

@@ -16,17 +16,17 @@ import net.ranides.assira.collection.ArrayUtils;
  * </p><p>
  * Uwaga! Klucz nie pozwala na bezpośredni dostęp lub modyfikację składowych, ale
  * jeśli składowe nie są <i>immutable</i>, a referencje do nich zostaną wykorzystane
- * do modyfikacji składowych, to również {@code CompositeKey} natychmiast 
+ * do modyfikacji składowych, to również {@code CompositeKey} natychmiast
  * odwzoruje te zmiany.
  * </p>
  * @author ranides
  */
 public class CompositeKey {
-    
+
     private final Object[] keys;
 
     /**
-     * Tworzy nowy klucz na podstawie podanych wartości. 
+     * Tworzy nowy klucz na podstawie podanych wartości.
      * @param keys
      */
     public CompositeKey(Object... keys) {
@@ -40,7 +40,7 @@ public class CompositeKey {
 
     @Override
     public int hashCode() {
-        return Arrays.deepHashCode(this.keys);
+        return Arrays.hashCode(this.keys);
     }
 
 }

+ 23 - 0
src/main/java/net/ranides/assira/math/PVMath.java

@@ -0,0 +1,23 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.math;
+
+/**
+ *
+ * @author ranides
+ */
+public final class PVMath {
+
+    private PVMath() {
+    // utility class
+    }
+
+    public static int rebaseCapacity(PVNumber value, int newbase) {
+        return (int) Math.ceil( value.capacity() * Math.log(value.base()) / Math.log(newbase) );
+    }
+
+}

+ 189 - 0
src/main/java/net/ranides/assira/math/PVNumber.java

@@ -0,0 +1,189 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.math;
+
+/**
+ * Number represented in "place-value notation" / "positional notation"
+ * @author ranides
+ */
+public abstract class PVNumber extends Number implements Cloneable, Comparable<PVNumber> {
+
+    protected static final int DIGITS_INT = 14;
+
+    protected static final int DIGITS_LONG = 24;
+
+    protected static final int DIGITS_FLOAT = 45;
+
+    protected static final int DIGITS_DOUBLE = 325;
+
+    /**
+     * base used by number
+     * @return
+     */
+    public abstract int base();
+
+    /**
+     * maximal number of digits
+     * @return
+     */
+    public abstract int capacity();
+
+    /**
+     * minimal exponent (can be negative)
+     * @return
+     */
+    public abstract int begin();
+
+    /**
+     * maximal exponent (can be negative)
+     * @return
+     */
+    public abstract int end();
+
+    /**
+     * get digit for passed exponent
+     * @param exponent
+     * @return
+     */
+    public abstract int get(int exponent);
+
+    /**
+     * set digit for passed exponent
+     * @param exponent
+     * @param value
+     */
+    public abstract void set(int exponent, int value);
+
+    /**
+     * actual number of digits
+     * @return
+     */
+    public int size() {
+        return end() - begin();
+    }
+
+    @Override
+    public int intValue() {
+        int ret = 0;
+        int b = base();
+        int r = 1;
+        for(int i=0, n=Math.min(DIGITS_INT,end()); i<=n; i++) {
+            ret += r*get(i);
+            r *= b;
+        }
+        return ret;
+    }
+
+    @Override
+    public long longValue() {
+        long ret = 0;
+        long b = base();
+        long r = 1;
+        for(int i=0, n=Math.min(DIGITS_LONG,end()); i<=n; i++) {
+            ret += r*get(i);
+            r *= b;
+        }
+        return ret;
+    }
+
+    @Override
+    public float floatValue() {
+        float b = base();
+        float ret = 0;
+        float r = 1.0f;
+        for(int i=0, n=Math.min(DIGITS_FLOAT,end()); i<=n; i++) {
+            ret += r * get(i);
+            r *= b;
+        }
+        r = 1.0f / b;
+        for(int i=-1, n=Math.max(-DIGITS_FLOAT, begin()); i>=n; i--) {
+            ret += r * get(i);
+            r /= b;
+        }
+        return ret;
+    }
+
+    @Override
+    public double doubleValue() {
+        double b = base();
+        double ret = 0;
+        double r = 1.0f;
+        for(int i=0, n=Math.min(DIGITS_DOUBLE,end()); i<=n; i++) {
+            ret += r * get(i);
+            r *= b;
+        }
+        r = 1.0f / b;
+        for(int i=-1, n=Math.max(-DIGITS_DOUBLE, begin()); i>=n; i--) {
+            ret += r * get(i);
+            r /= b;
+        }
+        return ret;
+    }
+
+    @Override
+    public String toString() {
+        return toString(63,63); // maximal length of string: 127 or 255
+    }
+
+    public String toString(int imax, int fmax) {
+        String sep = base()<=10 ? "" : " ";
+        StringBuilder ret = new StringBuilder();
+
+        for(int i=Math.min(imax-1,end()); i>0; i--) {
+            ret.append( get(i) ).append(sep);
+        }
+        ret.append( get(0) );
+        if(begin() < 0) {
+            ret.append(sep).append(".");
+        }
+        for(int i=-1, mi=Math.max(-fmax,begin()); i>=mi; i--) {
+            ret.append(sep).append( get(i) );
+        }
+
+        return ret.toString();
+    }
+
+    @Override
+    public int compareTo(PVNumber value) {
+        if( value.base() != base() ) {
+            // @todo (assira # 7) PVNumber: comparing different bases
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+        int rr = end() - value.end();
+        if(rr != 0) {
+            return rr;
+        }
+        for(int i=end(), n=Math.min(begin(), value.begin()); i>=n; i--) {
+            int dr = get(i) - value.get(i);
+            if(dr != 0) {
+                return dr;
+            }
+        }
+        return 0;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        if(object instanceof PVNumber) {
+            return compareTo((PVNumber)object) == 0;
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        int ret = 0;
+        int b = 19 * base();
+        for(int i=begin(), c=0, n=end(); i<=n && c<16; i++, c++) {
+            ret = (b*ret) ^ get(i);
+        }
+        return ret;
+    }
+
+
+
+}

+ 129 - 0
src/test/java/net/ranides/assira/math/PVNumberTest.java

@@ -0,0 +1,129 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.math;
+
+import java.util.SortedMap;
+import java.util.TreeMap;
+import net.ranides.assira.text.StringUtils;
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+/**
+ * 
+ * @author ranides
+ */
+ public class PVNumberTest {
+
+    private static final class RINumber extends PVNumber {
+
+        private final int base;
+        private final SortedMap<Integer, Integer> data;
+
+        public RINumber(int base) {
+            this.base = base;
+            this.data = new TreeMap<Integer, Integer>();
+            this.data.put(0, 0);
+        }
+
+        public RINumber(String value) {
+            this(10);
+            String[] parts = value.split("\\.", 2);
+
+            int im = parts[0].length();
+            for(int i=0; i<im; i++) {
+                data.put(im-i-1, parts[0].charAt(i)-'0');
+            }
+            if( parts.length > 1) {
+                int fm = parts[1].length();
+                for(int i=0; i<fm; i++) {
+                    data.put(-i-1, parts[1].charAt(i)-'0');
+                }
+            }
+        }
+
+        @Override
+        public int base() {
+            return base;
+        }
+
+        @Override
+        public int capacity() {
+            return Integer.MAX_VALUE;
+        }
+
+        @Override
+        public int begin() {
+            return data.firstKey();
+        }
+
+        @Override
+        public int end() {
+            return data.lastKey();
+        }
+
+        @Override
+        public int get(int exponent) {
+            return data.containsKey(exponent) ? data.get(exponent) : 0;
+        }
+
+        @Override
+        public void set(int exponent, int value) {
+            data.put(exponent, value);
+        }
+
+//        public static RINumber valueOf(PVNumber value) {
+//            RINumber ret = new RINumber(value.base());
+//            for(int i=value.begin(), n=value.end(); i<=n; i++) {
+//                ret.set(i, value.get(i));
+//            }
+//            return ret;
+//        }
+
+    }
+
+    public PVNumberTest() {
+    }
+
+    @Test
+    public void testSimple() {
+
+        PVNumber a = new RINumber("367.75");
+
+        assertEquals(-2, a.begin());
+        assertEquals(+2, a.end());
+
+        assertEquals(367, a.intValue() );
+        assertEquals(367.75, a.doubleValue(), 1e-6);
+        assertEquals(367.75, a.floatValue(), 1e-6);
+        assertEquals("367.75", a.toString() );
+
+
+        System.out.println( new RINumber("1234567.1234567").toString(4,2) );
+
+        System.out.println( new RINumber("0."+D(20)+"23456789").floatValue() );
+
+        System.out.println( new RINumber("0."+D(40)+"23456789").floatValue() );
+
+        System.out.println( new RINumber("0."+D(315)+"23456789").doubleValue() );
+
+        System.out.println( new RINumber("0."+D(30)+"23456789").doubleValue() );
+
+        System.out.println( new RINumber("367.75").compareTo(new RINumber("367.72")) > 0);
+        System.out.println( new RINumber("367.72").compareTo(new RINumber("367.75")) < 0);
+        System.out.println( new RINumber("367.75").compareTo(new RINumber("3677.5")) < 0);
+        System.out.println( new RINumber("3677.5").compareTo(new RINumber("367.75")) > 0);
+
+        System.out.println( new RINumber("15").compareTo(new RINumber("14")) > 0);
+        System.out.println( new RINumber("14").compareTo(new RINumber("15")) < 0);
+
+    }
+
+    private static String D(int n) {
+        return StringUtils.nCopies(n, '0').toString();
+    }
+
+}