blob: 3d204d1a91e0845c2fb96b7143c0644cd2b7cfcb [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package opconst
import (
"math/big"
)
// bigComplex represents a constant complex number. The semantics are similar
// to big.Rat; methods are typically of the form:
// func (z *bigComplex) Op(x, y *bigComplex) *bigComplex
// and implement operations z = x Op y with the result as receiver.
type bigComplex struct {
re, im big.Rat
}
func newComplex(re, im *big.Rat) *bigComplex {
return &bigComplex{*re, *im}
}
// realComplex returns a bigComplex with real part re, and imaginary part zero.
func realComplex(re *big.Rat) *bigComplex {
return &bigComplex{re: *re}
}
// imagComplex returns a bigComplex with real part zero, and imaginary part im.
func imagComplex(im *big.Rat) *bigComplex {
return &bigComplex{im: *im}
}
func (z *bigComplex) SetComplex128(c complex128) *bigComplex {
z.re.SetFloat64(real(c))
z.im.SetFloat64(imag(c))
return z
}
func (z *bigComplex) Equal(x *bigComplex) bool {
return z.re.Cmp(&x.re) == 0 && z.im.Cmp(&x.im) == 0
}
func (z *bigComplex) Add(x, y *bigComplex) *bigComplex {
z.re.Add(&x.re, &y.re)
z.im.Add(&x.im, &y.im)
return z
}
func (z *bigComplex) Sub(x, y *bigComplex) *bigComplex {
z.re.Sub(&x.re, &y.re)
z.im.Sub(&x.im, &y.im)
return z
}
func (z *bigComplex) Neg(x *bigComplex) *bigComplex {
z.re.Neg(&x.re)
z.im.Neg(&x.im)
return z
}
func (z *bigComplex) Mul(x, y *bigComplex) *bigComplex {
// (a+bi) * (c+di) = (ac-bd) + (bc+ad)i
var ac, ad, bc, bd big.Rat
ac.Mul(&x.re, &y.re)
ad.Mul(&x.re, &y.im)
bc.Mul(&x.im, &y.re)
bd.Mul(&x.im, &y.im)
z.re.Sub(&ac, &bd)
z.im.Add(&bc, &ad)
return z
}
func (z *bigComplex) Div(x, y *bigComplex) (*bigComplex, error) {
// (a+bi) / (c+di) = (a+bi)(c-di) / (c+di)(c-di)
// = ((ac+bd) + (bc-ad)i) / (cc+dd)
// = (ac+bd)/(cc+dd) + ((bc-ad)/(cc+dd))i
a, b, c, d := &x.re, &x.im, &y.re, &y.im
var ac, ad, bc, bd, cc, dd, ccdd big.Rat
ac.Mul(a, c)
ad.Mul(a, d)
bc.Mul(b, c)
bd.Mul(b, d)
cc.Mul(c, c)
dd.Mul(d, d)
ccdd.Add(&cc, &dd)
if ccdd.Cmp(bigRatZero) == 0 {
return nil, errDivZero
}
z.re.Add(&ac, &bd).Quo(&z.re, &ccdd)
z.im.Sub(&bc, &ad).Quo(&z.im, &ccdd)
return z, nil
}