2012-04-07 6 views
5

Ich implementiere eine schnellere BigInt Implementierung und ich bin mir nicht sicher, wie weit ich gehen sollte, um Interop mit der zugrunde liegenden Plattform bereitzustellen.Welche Probleme muss ich erwarten, wenn Sie Reflection als Schnittstelle zu java.math.BigInteger verwenden?

Heute BigInt wickelt nur einen BigInteger und der Wert bigInteger gibt nur den verpackten Wert:

class BigInt(val bigInteger: BigInteger) ... 

Weil ich nicht bin ein Java-Typ wickeln, würde ich so etwas wie

final class BigInt private(final val signum: Int, 
          final private[math] val arr: Array[Int]) 
    def bigInteger: java.math.BigInteger = { 
    // Avoid copying of potentially large arrays. 
    val ctor = classOf[java.math.BigInteger] 
       .getDeclaredConstructor(classOf[Array[Int]], classOf[Int]) 
    ctor setAccessible true 
    ctor.newInstance(arr, signum.asInstanceOf[Object]) 
    } 
... 
} 
zu tun haben

Kann dies zu Problemen führen oder gibt es einen besseren Weg?

+0

Ich weiß nicht, wie groß die Zahl ist, aber das Kopieren einer kleinen Reihe von Ints könnte schneller sein als mit Reflexion ... – paradigmatic

+0

Ja, sicher. Für kleine Arrays spielt das keine Rolle, aber die Größe der Zahlen ist nur durch den RAM begrenzt. Ich möchte einfach keine Speicher essen, wenn ich Daten von einer unveränderlichen Datenstruktur in eine andere verlagern möchte. – soc

+0

Die Anzahl der Atome im gesamten Universum wird üblicherweise auf 10^80 geschätzt. Mit nur 9 * 32 Bits können Sie jedem einen eindeutigen Index zuweisen. Ich glaube fest, dass wenn Sie eine natürliche Zahl größer als das brauchen, es ist wahrscheinlich ein Fehler oder ein Designfehler ... – paradigmatic

Antwort

3

Im Allgemeinen, wenn ich Leute privat gesehen habe (oder auf andere Weise ohne Papiere) Konstrukteuren oder Methoden wie diese, sie fangen NoSuchMethodException und bieten eine Alternative:

object BigInt { 
    import java.math.BigInteger 

    private val toBigInteger: (Array[Int], Int) => BigInteger = try { 
    val ctor = classOf[BigInteger].getDeclaredConstructor(
     classOf[Array[Int]], classOf[Int] 
    ) 
    ctor.setAccessible(true) 

    (arr, signum) => ctor.newInstance(arr, signum.asInstanceOf[Object]) 
    } catch { case _: NoSuchMethodException => 
    (arr, signum) => 
     val buffer = java.nio.ByteBuffer.allocate(arr.length * 4) 
     buffer.asIntBuffer.put(arr) 
     new BigInteger(signum, buffer.array) 
    } 
} 

final class BigInt(final val signum: Int, final val arr: Array[Int]) { 
    def bigInteger = BigInt.toBigInteger(arr, signum) 
} 

ich auch die Reflexion Unternehmen verschoben haben ausgeschaltet ein begleitendes Objekt, damit Sie nicht jedes Mal, wenn Sie anrufen, bigInteger bezahlen.

+0

Interessanter Ansatz, danke! – soc

+0

Müsste ich nicht nach 'SecurityException' anstelle von' NoSuchMethodException' Ausschau halten? Amüsant ist, dass JavaDoc diesen Konstruktor sogar als öffentlich bezeichnet, also glaube ich nicht, dass er jemals verschwinden wird. – soc