jliszka / probability-monad

Apache License 2.0
263 stars 38 forks source link

Make the alias method numerically stable #5

Closed jcazevedo closed 10 years ago

jcazevedo commented 10 years ago

This PR makes the alias method numerically stable, as recommended here. It fixes match errors in cases such as the following:

scala> discrete((0 until 300).map(_ -> 10.0 / 3.0):_*)
scala.MatchError: List() (of class scala.collection.immutable.Nil$)
        at probability_monad.Distribution$$anon$19.alias(Distribution.scala:281)
        at probability_monad.Distribution$$anon$19.<init>(Distribution.scala:291)
        at probability_monad.Distribution$.discrete(Distribution.scala:270)
        at .<init>(<console>:17)
        at .<clinit>(<console>)
        at .<init>(<console>:7)
        at .<clinit>(<console>)
        at $print(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:601)
        at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:734)
        at scala.tools.nsc.interpreter.IMain$Request.loadAndRun(IMain.scala:983)
        at scala.tools.nsc.interpreter.IMain.loadAndRunReq$1(IMain.scala:573)
        at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:604)
        at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:568)
        at scala.tools.nsc.interpreter.ILoop.reallyInterpret$1(ILoop.scala:745)
        at scala.tools.nsc.interpreter.ILoop.interpretStartingWith(ILoop.scala:790)
        at scala.tools.nsc.interpreter.ILoop.command(ILoop.scala:702)
        at scala.tools.nsc.interpreter.ILoop.processLine$1(ILoop.scala:566)
        at scala.tools.nsc.interpreter.ILoop.innerLoop$1(ILoop.scala:573)
        at scala.tools.nsc.interpreter.ILoop.loop(ILoop.scala:576)
        at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply$mcZ$sp(ILoop.scala:867)
        at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:822)
        at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:822)
        at scala.tools.nsc.util.ScalaClassLoader$.savingContextLoader(ScalaClassLoader.scala:135)
        at scala.tools.nsc.interpreter.ILoop.process(ILoop.scala:822)
        at scala.tools.nsc.interpreter.ILoop.main(ILoop.scala:889)
        at xsbt.ConsoleInterface.run(ConsoleInterface.scala:57)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:601)
        at sbt.compiler.AnalyzingCompiler.call(AnalyzingCompiler.scala:73)
        at sbt.compiler.AnalyzingCompiler.console(AnalyzingCompiler.scala:64)
        at sbt.Console.console0$1(Console.scala:23)
        at sbt.Console$$anonfun$apply$2$$anonfun$apply$1.apply$mcV$sp(Console.scala:24)
        at sbt.TrapExit$.executeMain$1(TrapExit.scala:33)
        at sbt.TrapExit$$anon$1.run(TrapExit.scala:42)