scalanlp / breeze

Breeze is/was a numerical processing library for Scala.
https://www.scalanlp.org
Apache License 2.0
3.45k stars 692 forks source link

how to achieve the operations like '+', '-' of the breeze.linalg.DenseMatrix[scala.math.BigDecimal] type ? #510

Closed kute closed 8 years ago

kute commented 8 years ago

i see in scaladoc: (DenseMatrix)[http://www.scalanlp.org/api/breeze/#breeze.linalg.DenseMatrix] it is to say that It is designed to be fast: Double- (and potentially Float-)valued DenseMatrices can be used with blas, and support operations to that effect.

now i want to change the type of DenseMatrix, when i define the DenseMatrix[BigDecimal] type instead of DenseMatrix[Double], i think BigDecimal is more accurate than Double.

val a: DenseMatrix[BigDecimal] = ...
val b: DenseMatrix[BigDecimal] = ...
 a + b // it report error

could not find implicit value for parameter op: breeze.linalg.operators.OpAdd.Impl2[breeze.linalg.DenseMatrix[scala.math.BigDecimal],breeze.linalg.DenseMatrix[scala.math.BigDecimal],That]

how can i do this ?

dlwh commented 8 years ago

operators aren't implemented for these. In principle doing the following should work:

import breeze.math.Field._

// make sure this is imported anywhere you want to use BigDecimal operators
implicit object fieldBigDecimal extends Field[BigDecimal] {
  def zero = BigDecimal(0L)
  def one = BigDecimal(1L)
  def ==(a : BigDecimal, b : BigDecimal) = a == b
  def !=(a : BigDecimal, b : BigDecimal) = a != b
  def +(a : BigDecimal, b : BigDecimal) = a + b

  // etc.
}

val a: DenseMatrix[BigDecimal] = ...
val b: DenseMatrix[BigDecimal] = ...
 a + b

This should work, but it might not work for everything. please update this issue with any problems you find.

On Tue, Mar 15, 2016 at 5:29 AM, kute notifications@github.com wrote:

i see in scaladoc: (DenseMatrix)[ http://www.scalanlp.org/api/breeze/#breeze.linalg.DenseMatrix] it is to say that It is designed to be fast: Double- (and potentially Float-)valued DenseMatrices can be used with blas, and support operations to that effect.

now i want to change the type of DenseMatrix, when i define the DenseMatrix[BigDecimal] type instead of DenseMatrix[Double], i think BigDecimal is more accurate than Double.

val a: DenseMatrix[BigDecimal] = ... val b: DenseMatrix[BigDecimal] = ... a + b // it report error

could not find implicit value for parameter op: breeze.linalg.operators.OpAdd.Impl2[breeze.linalg.DenseMatrix[scala.math.BigDecimal],breeze.linalg.DenseMatrix[scala.math.BigDecimal],That]

how can i do this ?

— You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/scalanlp/breeze/issues/510

kute commented 8 years ago

thks ! @dlwh

KLordy commented 8 years ago

So cool to see you!@dlwh
I have met the same problem,and it confused me for a long time.When I follow your solution,I found it not work for a_b. When I call a_b,I got the following error: Error:(53, 12) diverging implicit expansion for type breeze.linalg.operators.OpMulMatrix.Impl2[breeze.linalg.DenseMatrix[BigDecimal],breeze.linalg.DenseMatrix[BigDecimal],That] starting with method canMulM_M_def in trait DenseMatrixOpsLowPrio println(a*a) ^ How can I do this?

dlwh commented 8 years ago

ugh, that's just a bug. I'll see if I can fix

On Wed, Mar 16, 2016 at 11:11 PM, KLordy notifications@github.com wrote:

So cool to see you!@dlwh https://github.com/dlwh

I have met the same problem,and it confused me for a long time.When I follow your solution,I found it not work for a _b. When I call a_b,I got the following error: Error:(53, 12) diverging implicit expansion for type breeze.linalg.operators.OpMulMatrix.Impl2[breeze.linalg.DenseMatrix[BigDecimal],breeze.linalg.DenseMatrix[BigDecimal],That] starting with method canMulM_M_def in trait DenseMatrixOpsLowPrio println(a*a) ^ How can I do this?

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/scalanlp/breeze/issues/510#issuecomment-197723789

dlwh commented 8 years ago

publishing artifacts now

dlwh commented 8 years ago

to be clear: I have not optimized this at all, and it will be extremely slow

nathanhack commented 8 years ago

I ran into a problem with trying to use BigDecimals with version breeze_2.11-0.12

Error:(91, 24) ambiguous implicit values: both method ObjectZero in trait ZeroVeryLowPriority of type [T <: AnyRef]=> breeze.storage.Zero[T] and method zeroFromSemiring in trait ZeroLowPriority of type [T](implicit evidence$1: breeze.math.Semiring[T])breeze.storage.Zero[T] match expected type breeze.storage.Zero[scala.math.BigDecimal]

When trying either of the following: val a: DenseMatrix[BigDecimal] = DenseMatrix.create[BigDecimal](2, 2, Array(BigDecimal(1), BigDecimal(2), BigDecimal(3), BigDecimal(4)))

val a = DenseMatrix((BigDecimal(1), BigDecimal(2)),(BigDecimal(3), BigDecimal(4)))

My work around was to add this (maybe it could be added to the Zero class? not sure if it should be there still figuring out the classes and structure): import breeze.storage.Zero implicit object BigDecimalZero extends Zero[BigDecimal] { override def zero = BigDecimal(0) }

MY ISSUE: I'm having trouble figuring out what to do with this error:

Error:(98, 26) could not find implicit value for parameter op: breeze.linalg.operators.OpMulMatrix.Impl2[breeze.linalg.Transpose[breeze.linalg.DenseVector[scala.math.BigDecimal]],scala.math.BigDecimal,That] a(0, ::) := a(0, ::) * BigDecimal(2.0)

It works for scalar addition ( a(0, ::) := a(0, ::) + BigDecimal(2.0)) which made me think it would work for scalar multiplication, any ideas?

KLordy commented 8 years ago

First of all, a(0, ::) := a(0, ::) * BigDecimal(2.0) means you wanna to multiply 2.0 to the first row of a?If so, this is clear. the error message have provided some useful information.When you use a(0, ::) , you will get a Transpose[DenseVector[BigDecimal]],this type seems not work for operations like ' := ' and ' * '.To make it work,you should change it to DenseVector[BigDecimal] or DenseMatrix[BigDecimal]. My test codes are as below:val a: DenseMatrix[BigDecimal] = DenseMatrix.create[BigDecimal](2, 2, Array(BigDecimal(1), BigDecimal(2), BigDecimal(3), BigDecimal(4))) val c = a(0,::).inner val muls = (c.toDenseMatrix).*(BigDecimal(2.0))(DenseMatrix.op_DM_S_OpMulMatrix) c.:=(muls.toDenseVector)(DenseVector.implOpSet_DV_DV_InPlace[BigDecimal]) It may seems a little complicated than a(0, ::) := a(0, ::) * BigDecimal(2.0), but this is what i thought about.When you use Breeze to operate matrix,you should be careful about the return type of your operation.Many operations only work for DenseVector and DenseMatrix,so the wrong type will certainly not work. @nathanhack