// Convert attempts to convert the constant x to a given type. // If the attempt is successful, the result is the new constant; // otherwise the result is invalid. func (x Const) Convert(typ *Type) Const { // TODO(gri) implement this switch x := x.Val.(type) { //case bool: case *big.Int: switch Underlying(*typ) { case Float32, Float64: var z big.Rat z.SetInt(x) return Const{&z} case String: return Const{string(x.Int64())} case Complex64, Complex128: var z big.Rat z.SetInt(x) return Const{Cmplx{&z, &big.Rat{}}} } case *big.Rat: switch Underlying(*typ) { case Byte, Int, Uint, Int8, Uint8, Int16, Uint16, Int32, Uint32, Int64, Uint64: // Convert to an integer. Remove the fractional component. num, denom := x.Num(), x.Denom() var z big.Int z.Quo(num, denom) return Const{&z} } //case Cmplx: //case string: } //panic("unimplemented") return x }
func binaryFloatOp(x *big.Rat, op token.Token, y *big.Rat) interface{} { var z big.Rat switch op { case token.ADD: return z.Add(x, y) case token.SUB: return z.Sub(x, y) case token.MUL: return z.Mul(x, y) case token.QUO: return z.Quo(x, y) case token.EQL: return x.Cmp(y) == 0 case token.NEQ: return x.Cmp(y) != 0 case token.LSS: return x.Cmp(y) < 0 case token.LEQ: return x.Cmp(y) <= 0 case token.GTR: return x.Cmp(y) > 0 case token.GEQ: return x.Cmp(y) >= 0 } panic("unreachable") }
func renderRat(img *image.RGBA) { var yminR, ymaxMinR, heightR big.Rat yminR.SetInt64(ymin) ymaxMinR.SetInt64(ymax - ymin) heightR.SetInt64(height) var xminR, xmaxMinR, widthR big.Rat xminR.SetInt64(xmin) xmaxMinR.SetInt64(xmax - xmin) widthR.SetInt64(width) var y, x big.Rat for py := int64(0); py < height; py++ { // y := float64(py)/height*(ymax-ymin) + ymin y.SetInt64(py) y.Quo(&y, &heightR) y.Mul(&y, &ymaxMinR) y.Add(&y, &yminR) for px := int64(0); px < width; px++ { // x := float64(px)/width*(xmax-xmin) + xmin x.SetInt64(px) x.Quo(&x, &widthR) x.Mul(&x, &xmaxMinR) x.Add(&x, &xminR) c := mandelbrotRat(&x, &y) if c == nil { c = color.Black } img.Set(int(px), int(py), c) } } }
// Total returns the total of an Usage func (u *Usage) Total() *big.Rat { //return math.Min(u.Object.UnitPrice * u.BillableQuantity(), u.Object.UnitPriceCap) total := new(big.Rat).Mul(u.BillableQuantity(), u.Object.UnitPrice) total = total.Quo(total, u.Object.UnitQuantity) return ratMin(total, u.Object.UnitPriceCap) }
func String(v xdr.Int64) string { var f, o, r big.Rat f.SetInt64(int64(v)) o.SetInt64(One) r.Quo(&f, &o) return r.FloatString(7) }
func GasPrice(bp, gl, ep *big.Int) *big.Int { BP := new(big.Rat).SetInt(bp) GL := new(big.Rat).SetInt(gl) EP := new(big.Rat).SetInt(ep) GP := new(big.Rat).Quo(BP, GL) GP = GP.Quo(GP, EP) return GP.Mul(GP, etherInWei).Num() }
func tans(m []mTerm) *big.Rat { if len(m) == 1 { return tanEval(m[0].a, big.NewRat(m[0].n, m[0].d)) } half := len(m) / 2 a := tans(m[:half]) b := tans(m[half:]) r := new(big.Rat) return r.Quo(new(big.Rat).Add(a, b), r.Sub(one, r.Mul(a, b))) }
// floatString returns the string representation for a // numeric value v in normalized floating-point format. func floatString(v exact.Value) string { if exact.Sign(v) == 0 { return "0.0" } // x != 0 // convert |v| into a big.Rat x x := new(big.Rat).SetFrac(absInt(exact.Num(v)), absInt(exact.Denom(v))) // normalize x and determine exponent e // (This is not very efficient, but also not speed-critical.) var e int for x.Cmp(ten) >= 0 { x.Quo(x, ten) e++ } for x.Cmp(one) < 0 { x.Mul(x, ten) e-- } // TODO(gri) Values such as 1/2 are easier to read in form 0.5 // rather than 5.0e-1. Similarly, 1.0e1 is easier to read as // 10.0. Fine-tune best exponent range for readability. s := x.FloatString(100) // good-enough precision // trim trailing 0's i := len(s) for i > 0 && s[i-1] == '0' { i-- } s = s[:i] // add a 0 if the number ends in decimal point if len(s) > 0 && s[len(s)-1] == '.' { s += "0" } // add exponent and sign if e != 0 { s += fmt.Sprintf("e%+d", e) } if exact.Sign(v) < 0 { s = "-" + s } // TODO(gri) If v is a "small" fraction (i.e., numerator and denominator // are just a small number of decimal digits), add the exact fraction as // a comment. For instance: 3.3333...e-1 /* = 1/3 */ return s }
func sexToDec(deg, min, sec *big.Rat, dir string) *big.Rat { // sexagesimal (base 60) to decimal // https://imm.dtf.wa.gov.au/helpfiles/Latitude_Longitude_conversion_hlp.htm deg.Add(deg, min.Quo(min, big.NewRat(60, 1))) deg.Add(deg, sec.Quo(sec, big.NewRat(3600, 1))) // N and E are the positive directions (like on an x,y axis) if dir == "S" || dir == "W" { deg.Neg(deg) } return deg }
func tanEval(coef int64, f *big.Rat) *big.Rat { if coef == 1 { return f } if coef < 0 { r := tanEval(-coef, f) return r.Neg(r) } ca := coef / 2 cb := coef - ca a := tanEval(ca, f) b := tanEval(cb, f) r := new(big.Rat) return r.Quo(new(big.Rat).Add(a, b), r.Sub(one, r.Mul(a, b))) }
func binaryCmplxOp(x cmplx, op token.Token, y cmplx) interface{} { a, b := x.re, x.im c, d := y.re, y.im switch op { case token.ADD: // (a+c) + i(b+d) var re, im big.Rat re.Add(a, c) im.Add(b, d) return cmplx{&re, &im} case token.SUB: // (a-c) + i(b-d) var re, im big.Rat re.Sub(a, c) im.Sub(b, d) return cmplx{&re, &im} case token.MUL: // (ac-bd) + i(bc+ad) var ac, bd, bc, ad big.Rat ac.Mul(a, c) bd.Mul(b, d) bc.Mul(b, c) ad.Mul(a, d) var re, im big.Rat re.Sub(&ac, &bd) im.Add(&bc, &ad) return cmplx{&re, &im} case token.QUO: // (ac+bd)/s + i(bc-ad)/s, with s = cc + dd var ac, bd, bc, ad, s big.Rat ac.Mul(a, c) bd.Mul(b, d) bc.Mul(b, c) ad.Mul(a, d) s.Add(c.Mul(c, c), d.Mul(d, d)) var re, im big.Rat re.Add(&ac, &bd) re.Quo(&re, &s) im.Sub(&bc, &ad) im.Quo(&im, &s) return cmplx{&re, &im} case token.EQL: return a.Cmp(c) == 0 && b.Cmp(d) == 0 case token.NEQ: return a.Cmp(c) != 0 || b.Cmp(d) != 0 } panic("unreachable") }
// ratScale multiplies x by 10**exp. func ratScale(x *big.Rat, exp int) { if exp < 0 { x.Inv(x) ratScale(x, -exp) x.Inv(x) return } for exp >= 9 { x.Quo(x, bigRatBillion) exp -= 9 } for exp >= 1 { x.Quo(x, bigRatTen) exp-- } }
func sqrtFloat(x *big.Rat) *big.Rat { t1 := new(big.Rat) t2 := new(big.Rat) t1.Set(x) // Iterate. // x{n} = (x{n-1}+x{0}/x{n-1}) / 2 for i := 0; i <= 4; i++ { if t1.Cmp(zero) == 0 { return t1 } t2.Quo(x, t1) t2.Add(t2, t1) t1.Mul(half, t2) } return t1 }
// ratExponent returns the power of ten that x would display in scientific notation. func ratExponent(x *big.Rat) int { if x.Sign() < 0 { x.Neg(x) } e := 0 invert := false if x.Num().Cmp(x.Denom()) < 0 { invert = true x.Inv(x) e++ } for x.Cmp(bigRatBillion) >= 0 { e += 9 x.Quo(x, bigRatBillion) } for x.Cmp(bigRatTen) > 0 { e++ x.Quo(x, bigRatTen) } if invert { return -e } return e }
// binaryOpConst returns the result of the constant evaluation x op y; // both operands must be of the same "kind" (boolean, numeric, or string). // If intDiv is true, division (op == token.QUO) is using integer division // (and the result is guaranteed to be integer) rather than floating-point // division. Division by zero leads to a run-time panic. // func binaryOpConst(x, y interface{}, op token.Token, intDiv bool) interface{} { x, y = matchConst(x, y) switch x := x.(type) { case bool: y := y.(bool) switch op { case token.LAND: return x && y case token.LOR: return x || y default: unreachable() } case int64: y := y.(int64) switch op { case token.ADD: // TODO(gri) can do better than this if is63bit(x) && is63bit(y) { return x + y } return normalizeIntConst(new(big.Int).Add(big.NewInt(x), big.NewInt(y))) case token.SUB: // TODO(gri) can do better than this if is63bit(x) && is63bit(y) { return x - y } return normalizeIntConst(new(big.Int).Sub(big.NewInt(x), big.NewInt(y))) case token.MUL: // TODO(gri) can do better than this if is32bit(x) && is32bit(y) { return x * y } return normalizeIntConst(new(big.Int).Mul(big.NewInt(x), big.NewInt(y))) case token.REM: return x % y case token.QUO: if intDiv { return x / y } return normalizeRatConst(new(big.Rat).SetFrac(big.NewInt(x), big.NewInt(y))) case token.AND: return x & y case token.OR: return x | y case token.XOR: return x ^ y case token.AND_NOT: return x &^ y default: unreachable() } case *big.Int: y := y.(*big.Int) var z big.Int switch op { case token.ADD: z.Add(x, y) case token.SUB: z.Sub(x, y) case token.MUL: z.Mul(x, y) case token.REM: z.Rem(x, y) case token.QUO: if intDiv { z.Quo(x, y) } else { return normalizeRatConst(new(big.Rat).SetFrac(x, y)) } case token.AND: z.And(x, y) case token.OR: z.Or(x, y) case token.XOR: z.Xor(x, y) case token.AND_NOT: z.AndNot(x, y) default: unreachable() } return normalizeIntConst(&z) case *big.Rat: y := y.(*big.Rat) var z big.Rat switch op { case token.ADD: z.Add(x, y) case token.SUB: z.Sub(x, y) case token.MUL: z.Mul(x, y) case token.QUO: z.Quo(x, y) default: unreachable() } return normalizeRatConst(&z) case complex: y := y.(complex) a, b := x.re, x.im c, d := y.re, y.im var re, im big.Rat switch op { case token.ADD: // (a+c) + i(b+d) re.Add(a, c) im.Add(b, d) case token.SUB: // (a-c) + i(b-d) re.Sub(a, c) im.Sub(b, d) case token.MUL: // (ac-bd) + i(bc+ad) var ac, bd, bc, ad big.Rat ac.Mul(a, c) bd.Mul(b, d) bc.Mul(b, c) ad.Mul(a, d) re.Sub(&ac, &bd) im.Add(&bc, &ad) case token.QUO: // (ac+bd)/s + i(bc-ad)/s, with s = cc + dd var ac, bd, bc, ad, s big.Rat ac.Mul(a, c) bd.Mul(b, d) bc.Mul(b, c) ad.Mul(a, d) s.Add(c.Mul(c, c), d.Mul(d, d)) re.Add(&ac, &bd) re.Quo(&re, &s) im.Sub(&bc, &ad) im.Quo(&im, &s) default: unreachable() } return normalizeComplexConst(complex{&re, &im}) case string: if op == token.ADD { return x + y.(string) } } unreachable() return nil }
func main() { f, err := os.Create("/tmp/profile") if err != nil { log.Fatal(err) } pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() p, _ := new(big.Int).SetString("233970423115425145524320034830162017933", 10) a := big.NewInt(-95051) b := big.NewInt(11279326) G := dh.NewEllipticCurve(a, b, p) gx := big.NewInt(182) gy, _ := new(big.Int).SetString("85518893674295321206118380980485522083", 10) g := dh.NewEllipticCurveElement(G, gx, gy) q, _ := new(big.Int).SetString("29246302889428143187362802287225875743", 10) GG := dh.NewGeneratedGroup(G, g, *q) var bias uint = 8 alice := dh.NewBiasedECDSA(GG, bias) var msg = []byte("I was a fiend") key, _ := new(big.Int).SetString("255bf9c75628ab469b45cced58755a3", 16) d := new(big.Rat).SetInt(key) numSigs := 22 B := dh.Matrix(make([]dh.Vector, numSigs+2)) zero := dh.Vector(make([]*big.Rat, numSigs+2)) for i, _ := range zero { zero[i] = new(big.Rat) } for i, _ := range B { B[i] = zero.Copy() } ct := big.NewRat(1, 1<<bias) B[len(B)-2][len(B)-2].Set(ct) cu := new(big.Rat).SetInt(q) cu.Quo(cu, big.NewRat(1<<bias, 1)) B[len(B)-1][len(B)-1].Set(cu) ts := make([]*big.Int, numSigs) us := make([]*big.Int, numSigs) for i := 0; i < numSigs; i++ { B[i][i].SetInt(q) r, s := alice.Sign(msg) t, u := transform(msg, r, s, q, bias) dt := new(big.Int).Mul(key, t) temp := new(big.Int).Sub(u, dt) temp.Mod(temp, q) temp.Sub(q, temp) log.Printf("\ndt: %x\nu: %x\nq-u-dt: %x\nq: %x", dt, u, temp, q) ts[i] = t us[i] = u B[len(B)-2][i] = new(big.Rat).SetInt(t) B[len(B)-1][i] = new(big.Rat).SetInt(u) } check := B[len(B)-1].Copy() check.Sub(B[len(B)-2].Copy().Scale(d)) for i := 0; i < numSigs; i++ { t := ts[i] dt := new(big.Int).Mul(key, t) m := new(big.Int).Div(dt, q) check.Add(B[i].Copy().Scale(new(big.Rat).SetInt(m))) } log.Printf("check=%s", check) B.LLL(big.NewRat(99, 100)) for _, v := range B { if v[len(v)-1].Cmp(cu) == 0 { log.Printf("%s", v) d := new(big.Rat) d.Sub(d, v[len(v)-2]) d.Mul(d, big.NewRat(1<<bias, 1)) guess := dh.Round(d).Num() log.Printf("Recovered key: %x", guess) log.Printf("Correct: %v", guess.Cmp(key) == 0) } } }
// Contract evaluation is done here. func (bm *BlockManager) ProcContract(tx *ethutil.Transaction, block *ethutil.Block, cb TxCallback) { // Instruction pointer pc := 0 blockInfo := bm.BlockInfo(block) contract := block.GetContract(tx.Hash()) if contract == nil { fmt.Println("Contract not found") return } Pow256 := ethutil.BigPow(2, 256) //fmt.Printf("# op arg\n") out: for { // The base big int for all calculations. Use this for any results. base := new(big.Int) // XXX Should Instr return big int slice instead of string slice? // Get the next instruction from the contract //op, _, _ := Instr(contract.state.Get(string(Encode(uint32(pc))))) nb := ethutil.NumberToBytes(uint64(pc), 32) o, _, _ := ethutil.Instr(contract.State().Get(string(nb))) op := OpCode(o) if !cb(0) { break } if Debug { //fmt.Printf("%-3d %-4s\n", pc, op.String()) } switch op { case oSTOP: break out case oADD: x, y := bm.stack.Popn() // (x + y) % 2 ** 256 base.Add(x, y) base.Mod(base, Pow256) // Pop result back on the stack bm.stack.Push(base) case oSUB: x, y := bm.stack.Popn() // (x - y) % 2 ** 256 base.Sub(x, y) base.Mod(base, Pow256) // Pop result back on the stack bm.stack.Push(base) case oMUL: x, y := bm.stack.Popn() // (x * y) % 2 ** 256 base.Mul(x, y) base.Mod(base, Pow256) // Pop result back on the stack bm.stack.Push(base) case oDIV: x, y := bm.stack.Popn() // floor(x / y) base.Div(x, y) // Pop result back on the stack bm.stack.Push(base) case oSDIV: x, y := bm.stack.Popn() // n > 2**255 if x.Cmp(Pow256) > 0 { x.Sub(Pow256, x) } if y.Cmp(Pow256) > 0 { y.Sub(Pow256, y) } z := new(big.Int) z.Div(x, y) if z.Cmp(Pow256) > 0 { z.Sub(Pow256, z) } // Push result on to the stack bm.stack.Push(z) case oMOD: x, y := bm.stack.Popn() base.Mod(x, y) bm.stack.Push(base) case oSMOD: x, y := bm.stack.Popn() // n > 2**255 if x.Cmp(Pow256) > 0 { x.Sub(Pow256, x) } if y.Cmp(Pow256) > 0 { y.Sub(Pow256, y) } z := new(big.Int) z.Mod(x, y) if z.Cmp(Pow256) > 0 { z.Sub(Pow256, z) } // Push result on to the stack bm.stack.Push(z) case oEXP: x, y := bm.stack.Popn() base.Exp(x, y, Pow256) bm.stack.Push(base) case oNEG: base.Sub(Pow256, bm.stack.Pop()) bm.stack.Push(base) case oLT: x, y := bm.stack.Popn() // x < y if x.Cmp(y) < 0 { bm.stack.Push(ethutil.BigTrue) } else { bm.stack.Push(ethutil.BigFalse) } case oLE: x, y := bm.stack.Popn() // x <= y if x.Cmp(y) < 1 { bm.stack.Push(ethutil.BigTrue) } else { bm.stack.Push(ethutil.BigFalse) } case oGT: x, y := bm.stack.Popn() // x > y if x.Cmp(y) > 0 { bm.stack.Push(ethutil.BigTrue) } else { bm.stack.Push(ethutil.BigFalse) } case oGE: x, y := bm.stack.Popn() // x >= y if x.Cmp(y) > -1 { bm.stack.Push(ethutil.BigTrue) } else { bm.stack.Push(ethutil.BigFalse) } case oNOT: x, y := bm.stack.Popn() // x != y if x.Cmp(y) != 0 { bm.stack.Push(ethutil.BigTrue) } else { bm.stack.Push(ethutil.BigFalse) } // Please note that the following code contains some // ugly string casting. This will have to change to big // ints. TODO :) case oMYADDRESS: bm.stack.Push(ethutil.BigD(tx.Hash())) case oTXSENDER: bm.stack.Push(ethutil.BigD(tx.Sender())) case oTXVALUE: bm.stack.Push(tx.Value) case oTXDATAN: bm.stack.Push(big.NewInt(int64(len(tx.Data)))) case oTXDATA: v := bm.stack.Pop() // v >= len(data) if v.Cmp(big.NewInt(int64(len(tx.Data)))) >= 0 { bm.stack.Push(ethutil.Big("0")) } else { bm.stack.Push(ethutil.Big(tx.Data[v.Uint64()])) } case oBLK_PREVHASH: bm.stack.Push(ethutil.Big(block.PrevHash)) case oBLK_COINBASE: bm.stack.Push(ethutil.Big(block.Coinbase)) case oBLK_TIMESTAMP: bm.stack.Push(big.NewInt(block.Time)) case oBLK_NUMBER: bm.stack.Push(blockInfo.Number) case oBLK_DIFFICULTY: bm.stack.Push(block.Difficulty) case oBASEFEE: // e = 10^21 e := big.NewInt(0).Exp(big.NewInt(10), big.NewInt(21), big.NewInt(0)) d := new(big.Rat) d.SetInt(block.Difficulty) c := new(big.Rat) c.SetFloat64(0.5) // d = diff / 0.5 d.Quo(d, c) // base = floor(d) base.Div(d.Num(), d.Denom()) x := new(big.Int) x.Div(e, base) // x = floor(10^21 / floor(diff^0.5)) bm.stack.Push(x) case oSHA256, oSHA3, oRIPEMD160: // This is probably save // ceil(pop / 32) length := int(math.Ceil(float64(bm.stack.Pop().Uint64()) / 32.0)) // New buffer which will contain the concatenated popped items data := new(bytes.Buffer) for i := 0; i < length; i++ { // Encode the number to bytes and have it 32bytes long num := ethutil.NumberToBytes(bm.stack.Pop().Bytes(), 256) data.WriteString(string(num)) } if op == oSHA256 { bm.stack.Push(base.SetBytes(ethutil.Sha256Bin(data.Bytes()))) } else if op == oSHA3 { bm.stack.Push(base.SetBytes(ethutil.Sha3Bin(data.Bytes()))) } else { bm.stack.Push(base.SetBytes(ethutil.Ripemd160(data.Bytes()))) } case oECMUL: y := bm.stack.Pop() x := bm.stack.Pop() //n := bm.stack.Pop() //if ethutil.Big(x).Cmp(ethutil.Big(y)) { data := new(bytes.Buffer) data.WriteString(x.String()) data.WriteString(y.String()) if secp256k1.VerifyPubkeyValidity(data.Bytes()) == 1 { // TODO } else { // Invalid, push infinity bm.stack.Push(ethutil.Big("0")) bm.stack.Push(ethutil.Big("0")) } //} else { // // Invalid, push infinity // bm.stack.Push("0") // bm.stack.Push("0") //} case oECADD: case oECSIGN: case oECRECOVER: case oECVALID: case oPUSH: pc++ bm.stack.Push(bm.mem[strconv.Itoa(pc)]) case oPOP: // Pop current value of the stack bm.stack.Pop() case oDUP: // Dup top stack x := bm.stack.Pop() bm.stack.Push(x) bm.stack.Push(x) case oSWAP: // Swap two top most values x, y := bm.stack.Popn() bm.stack.Push(y) bm.stack.Push(x) case oMLOAD: x := bm.stack.Pop() bm.stack.Push(bm.mem[x.String()]) case oMSTORE: x, y := bm.stack.Popn() bm.mem[x.String()] = y case oSLOAD: // Load the value in storage and push it on the stack x := bm.stack.Pop() // decode the object as a big integer decoder := ethutil.NewRlpDecoder([]byte(contract.State().Get(x.String()))) if !decoder.IsNil() { bm.stack.Push(decoder.AsBigInt()) } else { bm.stack.Push(ethutil.BigFalse) } case oSSTORE: // Store Y at index X x, y := bm.stack.Popn() contract.State().Update(x.String(), string(ethutil.Encode(y))) case oJMP: x := int(bm.stack.Pop().Uint64()) // Set pc to x - 1 (minus one so the incrementing at the end won't effect it) pc = x pc-- case oJMPI: x := bm.stack.Pop() // Set pc to x if it's non zero if x.Cmp(ethutil.BigFalse) != 0 { pc = int(x.Uint64()) pc-- } case oIND: bm.stack.Push(big.NewInt(int64(pc))) case oEXTRO: memAddr := bm.stack.Pop() contractAddr := bm.stack.Pop().Bytes() // Push the contract's memory on to the stack bm.stack.Push(getContractMemory(block, contractAddr, memAddr)) case oBALANCE: // Pushes the balance of the popped value on to the stack d := block.State().Get(bm.stack.Pop().String()) ether := ethutil.NewEtherFromData([]byte(d)) bm.stack.Push(ether.Amount) case oMKTX: value, addr := bm.stack.Popn() from, length := bm.stack.Popn() j := 0 dataItems := make([]string, int(length.Uint64())) for i := from.Uint64(); i < length.Uint64(); i++ { dataItems[j] = string(bm.mem[strconv.Itoa(int(i))].Bytes()) j++ } // TODO sign it? tx := ethutil.NewTransaction(string(addr.Bytes()), value, dataItems) // Add the transaction to the tx pool bm.server.txPool.QueueTransaction(tx) case oSUICIDE: //addr := bm.stack.Pop() } pc++ } bm.stack.Print() }
//export OFXTransactionCallback func OFXTransactionCallback(transaction_data C.struct_OfxTransactionData, data unsafe.Pointer) C.int { iobj := (*ImportObject)(data) itl := iobj.TransactionList transaction := new(Transaction) if transaction_data.name_valid != 0 { transaction.Description = C.GoString(&transaction_data.name[0]) } // if transaction_data.reference_number_valid != 0 { // fmt.Println("reference_number: ", C.GoString(&transaction_data.reference_number[0])) // } if transaction_data.date_posted_valid != 0 { transaction.Date = time.Unix(int64(transaction_data.date_posted), 0) } else if transaction_data.date_initiated_valid != 0 { transaction.Date = time.Unix(int64(transaction_data.date_initiated), 0) } if transaction_data.fi_id_valid != 0 { transaction.RemoteId = C.GoString(&transaction_data.fi_id[0]) } if transaction_data.amount_valid != 0 { split := new(Split) r := new(big.Rat) r.SetFloat64(float64(transaction_data.amount)) security, err := GetSecurity(itl.Account.SecurityId, itl.Account.UserId) if err != nil { if iobj.Error == nil { iobj.Error = err } return 1 } split.Amount = r.FloatString(security.Precision) if transaction_data.memo_valid != 0 { split.Memo = C.GoString(&transaction_data.memo[0]) } if transaction_data.check_number_valid != 0 { split.Number = C.GoString(&transaction_data.check_number[0]) } split.SecurityId = -1 split.AccountId = itl.Account.AccountId transaction.Splits = append(transaction.Splits, split) } else { if iobj.Error == nil { iobj.Error = errors.New("OFX transaction amount invalid") } return 1 } var security *Security var err error split := new(Split) units := new(big.Rat) if transaction_data.units_valid != 0 { units.SetFloat64(float64(transaction_data.units)) if transaction_data.security_data_valid != 0 { security_data := transaction_data.security_data_ptr if security_data.ticker_valid != 0 { s, err := GetSecurityByName(C.GoString(&security_data.ticker[0])) if err != nil { if iobj.Error == nil { iobj.Error = errors.New("Failed to find OFX transaction security: " + C.GoString(&security_data.ticker[0])) } return 1 } security = s } else { if iobj.Error == nil { iobj.Error = errors.New("OFX security ticker invalid") } return 1 } if security.Type == Stock && security_data.unique_id_valid != 0 && security_data.unique_id_type_valid != 0 && C.GoString(&security_data.unique_id_type[0]) == "CUSIP" { // Validate the security CUSIP, if possible if security.AlternateId != C.GoString(&security_data.unique_id[0]) { if iobj.Error == nil { iobj.Error = errors.New("OFX transaction security CUSIP failed to validate") } return 1 } } } else { security, err = GetSecurity(itl.Account.SecurityId, itl.Account.UserId) if err != nil { if iobj.Error == nil { iobj.Error = err } return 1 } } } else { // Calculate units from other available fields if its not present // units = - (amount + various fees) / unitprice units.SetFloat64(float64(transaction_data.amount)) fees := new(big.Rat) if transaction_data.fees_valid != 0 { fees.SetFloat64(float64(-transaction_data.fees)) } if transaction_data.commission_valid != 0 { commission := new(big.Rat) commission.SetFloat64(float64(-transaction_data.commission)) fees.Add(fees, commission) } units.Add(units, fees) units.Neg(units) if transaction_data.unitprice_valid != 0 && transaction_data.unitprice != 0 { unitprice := new(big.Rat) unitprice.SetFloat64(float64(transaction_data.unitprice)) units.Quo(units, unitprice) } // If 'units' wasn't present, assume we're using the account's security security, err = GetSecurity(itl.Account.SecurityId, itl.Account.UserId) if err != nil { if iobj.Error == nil { iobj.Error = err } return 1 } } split.Amount = units.FloatString(security.Precision) split.SecurityId = security.SecurityId split.AccountId = -1 transaction.Splits = append(transaction.Splits, split) if transaction_data.fees_valid != 0 { split := new(Split) r := new(big.Rat) r.SetFloat64(float64(-transaction_data.fees)) security, err := GetSecurity(itl.Account.SecurityId, itl.Account.UserId) if err != nil { if iobj.Error == nil { iobj.Error = err } return 1 } split.Amount = r.FloatString(security.Precision) split.Memo = "fees" split.SecurityId = itl.Account.SecurityId split.AccountId = -1 transaction.Splits = append(transaction.Splits, split) } if transaction_data.commission_valid != 0 { split := new(Split) r := new(big.Rat) r.SetFloat64(float64(-transaction_data.commission)) security, err := GetSecurity(itl.Account.SecurityId, itl.Account.UserId) if err != nil { if iobj.Error == nil { iobj.Error = err } return 1 } split.Amount = r.FloatString(security.Precision) split.Memo = "commission" split.SecurityId = itl.Account.SecurityId split.AccountId = -1 transaction.Splits = append(transaction.Splits, split) } // if transaction_data.payee_id_valid != 0 { // fmt.Println("payee_id: ", C.GoString(&transaction_data.payee_id[0])) // } transaction_list := append(*itl.Transactions, *transaction) iobj.TransactionList.Transactions = &transaction_list return 0 }
func (a *EqualSplitsAlgorithm) generateBoundaries() ([]tuple, error) { // generateBoundaries should work for a split_column whose type is integral // (both signed and unsigned) as well as for floating point values. // We perform the calculation of the boundaries using precise big.Rat arithmetic and only // truncate the result in the end if necessary. // We do this since using float64 arithmetic does not have enough precision: // for example, if max=math.MaxUint64 and min=math.MaxUint64-1000 then float64(min)==float64(max). // On the other hand, using integer arithmetic for the case where the split_column is integral // (i.e., rounding (max-min)/split_count to an integer) may cause very dissimilar interval // lengths or a large deviation between split_count and the number of query-parts actually // returned (consider min=0, max=9.5*10^6, and split_count=10^6). // Note(erez): We can probably get away with using big.Float with ~64 bits of precision which // will likely be more efficient. However, we defer optimizing this code until we see if this // is a bottle-neck. minValue, maxValue, err := a.executeMinMaxQuery() if err != nil { return nil, err } // If the table is empty, minValue and maxValue will be NULL. if (minValue.IsNull() && !maxValue.IsNull()) || !minValue.IsNull() && maxValue.IsNull() { panic(fmt.Sprintf("minValue and maxValue must both be NULL or both be non-NULL."+ " minValue: %v, maxValue: %v, splitParams.sql: %v", minValue, maxValue, a.splitParams.sql)) } if minValue.IsNull() { log.Infof("Splitting an empty table. splitParams.sql: %v. Query will not be split.", a.splitParams.sql) return []tuple{}, nil } min, err := valueToBigRat(minValue) if err != nil { panic(fmt.Sprintf("Failed to convert min to a big.Rat: %v, min: %+v", err, min)) } max, err := valueToBigRat(maxValue) if err != nil { panic(fmt.Sprintf("Failed to convert max to a big.Rat: %v, max: %+v", err, max)) } minCmpMax := min.Cmp(max) if minCmpMax > 0 { panic(fmt.Sprintf("max(splitColumn) < min(splitColumn): max:%v, min:%v", max, min)) } if minCmpMax == 0 { log.Infof("max(%v)=min(%v)=%v. splitParams.sql: %v. Query will not be split.", a.splitParams.splitColumns[0], a.splitParams.splitColumns[0], min, a.splitParams.sql) return []tuple{}, nil } // subIntervalSize = (max - min) / a.splitParams.splitCount subIntervalSize := new(big.Rat) subIntervalSize.Sub(max, min) subIntervalSize.Quo(subIntervalSize, new(big.Rat).SetInt64(a.splitParams.splitCount)) boundary := new(big.Rat).Set(min) // Copy min into boundary. var result []tuple for i := int64(1); i < a.splitParams.splitCount; i++ { boundary.Add(boundary, subIntervalSize) // Here boundary=min+i*subIntervalSize boundaryValue := bigRatToValue(boundary, a.splitParams.splitColumnTypes[0]) result = append(result, tuple{boundaryValue}) } return result, nil }
s.fatalf("cannot convert %q to int", p) } s.pushX(i) }}, }, // rational literal { regex(floatPat + "/" + floatPat), genericOp{0, 1, func(s *stack, p string) { i := strings.Index(p, "/") r0, ok0 := new(big.Rat).SetString(p[0:i]) r1, ok1 := new(big.Rat).SetString(p[i+1:]) if !ok0 || !ok1 { s.fatalf("bad rational %q", p) } s.pushX(r0.Quo(r0, r1)) }}, }, // float literal { regex(floatPat), genericOp{0, 1, func(s *stack, p string) { v, err := strconv.ParseFloat(p, 64) if err != nil { s.fatalf("bad float number %q", p) } s.pushX(v) }}, }, // rune literal {
func (vm *Vm) Process(contract *Contract, state *State, vars RuntimeVars) { vm.mem = make(map[string]*big.Int) vm.stack = NewStack() addr := vars.address // tx.Hash()[12:] // Instruction pointer pc := 0 if contract == nil { fmt.Println("Contract not found") return } Pow256 := ethutil.BigPow(2, 256) if ethutil.Config.Debug { ethutil.Config.Log.Debugf("# op\n") } stepcount := 0 totalFee := new(big.Int) out: for { stepcount++ // The base big int for all calculations. Use this for any results. base := new(big.Int) val := contract.GetMem(pc) //fmt.Printf("%x = %d, %v %x\n", r, len(r), v, nb) op := OpCode(val.Uint()) var fee *big.Int = new(big.Int) var fee2 *big.Int = new(big.Int) if stepcount > 16 { fee.Add(fee, StepFee) } // Calculate the fees switch op { case oSSTORE: y, x := vm.stack.Peekn() val := contract.Addr(ethutil.BigToBytes(x, 256)) if val.IsEmpty() && len(y.Bytes()) > 0 { fee2.Add(DataFee, StoreFee) } else { fee2.Sub(DataFee, StoreFee) } case oSLOAD: fee.Add(fee, StoreFee) case oEXTRO, oBALANCE: fee.Add(fee, ExtroFee) case oSHA256, oRIPEMD160, oECMUL, oECADD, oECSIGN, oECRECOVER, oECVALID: fee.Add(fee, CryptoFee) case oMKTX: fee.Add(fee, ContractFee) } tf := new(big.Int).Add(fee, fee2) if contract.Amount.Cmp(tf) < 0 { fmt.Println("Insufficient fees to continue running the contract", tf, contract.Amount) break } // Add the fee to the total fee. It's subtracted when we're done looping totalFee.Add(totalFee, tf) if ethutil.Config.Debug { ethutil.Config.Log.Debugf("%-3d %-4s", pc, op.String()) } switch op { case oSTOP: fmt.Println("") break out case oADD: x, y := vm.stack.Popn() // (x + y) % 2 ** 256 base.Add(x, y) base.Mod(base, Pow256) // Pop result back on the stack vm.stack.Push(base) case oSUB: x, y := vm.stack.Popn() // (x - y) % 2 ** 256 base.Sub(x, y) base.Mod(base, Pow256) // Pop result back on the stack vm.stack.Push(base) case oMUL: x, y := vm.stack.Popn() // (x * y) % 2 ** 256 base.Mul(x, y) base.Mod(base, Pow256) // Pop result back on the stack vm.stack.Push(base) case oDIV: x, y := vm.stack.Popn() // floor(x / y) base.Div(x, y) // Pop result back on the stack vm.stack.Push(base) case oSDIV: x, y := vm.stack.Popn() // n > 2**255 if x.Cmp(Pow256) > 0 { x.Sub(Pow256, x) } if y.Cmp(Pow256) > 0 { y.Sub(Pow256, y) } z := new(big.Int) z.Div(x, y) if z.Cmp(Pow256) > 0 { z.Sub(Pow256, z) } // Push result on to the stack vm.stack.Push(z) case oMOD: x, y := vm.stack.Popn() base.Mod(x, y) vm.stack.Push(base) case oSMOD: x, y := vm.stack.Popn() // n > 2**255 if x.Cmp(Pow256) > 0 { x.Sub(Pow256, x) } if y.Cmp(Pow256) > 0 { y.Sub(Pow256, y) } z := new(big.Int) z.Mod(x, y) if z.Cmp(Pow256) > 0 { z.Sub(Pow256, z) } // Push result on to the stack vm.stack.Push(z) case oEXP: x, y := vm.stack.Popn() base.Exp(x, y, Pow256) vm.stack.Push(base) case oNEG: base.Sub(Pow256, vm.stack.Pop()) vm.stack.Push(base) case oLT: x, y := vm.stack.Popn() // x < y if x.Cmp(y) < 0 { vm.stack.Push(ethutil.BigTrue) } else { vm.stack.Push(ethutil.BigFalse) } case oLE: x, y := vm.stack.Popn() // x <= y if x.Cmp(y) < 1 { vm.stack.Push(ethutil.BigTrue) } else { vm.stack.Push(ethutil.BigFalse) } case oGT: x, y := vm.stack.Popn() // x > y if x.Cmp(y) > 0 { vm.stack.Push(ethutil.BigTrue) } else { vm.stack.Push(ethutil.BigFalse) } case oGE: x, y := vm.stack.Popn() // x >= y if x.Cmp(y) > -1 { vm.stack.Push(ethutil.BigTrue) } else { vm.stack.Push(ethutil.BigFalse) } case oNOT: x, y := vm.stack.Popn() // x != y if x.Cmp(y) != 0 { vm.stack.Push(ethutil.BigTrue) } else { vm.stack.Push(ethutil.BigFalse) } case oMYADDRESS: vm.stack.Push(ethutil.BigD(addr)) case oTXSENDER: vm.stack.Push(ethutil.BigD(vars.sender)) case oTXVALUE: vm.stack.Push(vars.txValue) case oTXDATAN: vm.stack.Push(big.NewInt(int64(len(vars.txData)))) case oTXDATA: v := vm.stack.Pop() // v >= len(data) if v.Cmp(big.NewInt(int64(len(vars.txData)))) >= 0 { vm.stack.Push(ethutil.Big("0")) } else { vm.stack.Push(ethutil.Big(vars.txData[v.Uint64()])) } case oBLK_PREVHASH: vm.stack.Push(ethutil.BigD(vars.prevHash)) case oBLK_COINBASE: vm.stack.Push(ethutil.BigD(vars.coinbase)) case oBLK_TIMESTAMP: vm.stack.Push(big.NewInt(vars.time)) case oBLK_NUMBER: vm.stack.Push(big.NewInt(int64(vars.blockNumber))) case oBLK_DIFFICULTY: vm.stack.Push(vars.diff) case oBASEFEE: // e = 10^21 e := big.NewInt(0).Exp(big.NewInt(10), big.NewInt(21), big.NewInt(0)) d := new(big.Rat) d.SetInt(vars.diff) c := new(big.Rat) c.SetFloat64(0.5) // d = diff / 0.5 d.Quo(d, c) // base = floor(d) base.Div(d.Num(), d.Denom()) x := new(big.Int) x.Div(e, base) // x = floor(10^21 / floor(diff^0.5)) vm.stack.Push(x) case oSHA256, oSHA3, oRIPEMD160: // This is probably save // ceil(pop / 32) length := int(math.Ceil(float64(vm.stack.Pop().Uint64()) / 32.0)) // New buffer which will contain the concatenated popped items data := new(bytes.Buffer) for i := 0; i < length; i++ { // Encode the number to bytes and have it 32bytes long num := ethutil.NumberToBytes(vm.stack.Pop().Bytes(), 256) data.WriteString(string(num)) } if op == oSHA256 { vm.stack.Push(base.SetBytes(ethutil.Sha256Bin(data.Bytes()))) } else if op == oSHA3 { vm.stack.Push(base.SetBytes(ethutil.Sha3Bin(data.Bytes()))) } else { vm.stack.Push(base.SetBytes(ethutil.Ripemd160(data.Bytes()))) } case oECMUL: y := vm.stack.Pop() x := vm.stack.Pop() //n := vm.stack.Pop() //if ethutil.Big(x).Cmp(ethutil.Big(y)) { data := new(bytes.Buffer) data.WriteString(x.String()) data.WriteString(y.String()) if secp256k1.VerifyPubkeyValidity(data.Bytes()) == 1 { // TODO } else { // Invalid, push infinity vm.stack.Push(ethutil.Big("0")) vm.stack.Push(ethutil.Big("0")) } //} else { // // Invalid, push infinity // vm.stack.Push("0") // vm.stack.Push("0") //} case oECADD: case oECSIGN: case oECRECOVER: case oECVALID: case oPUSH: pc++ vm.stack.Push(contract.GetMem(pc).BigInt()) case oPOP: // Pop current value of the stack vm.stack.Pop() case oDUP: // Dup top stack x := vm.stack.Pop() vm.stack.Push(x) vm.stack.Push(x) case oSWAP: // Swap two top most values x, y := vm.stack.Popn() vm.stack.Push(y) vm.stack.Push(x) case oMLOAD: x := vm.stack.Pop() vm.stack.Push(vm.mem[x.String()]) case oMSTORE: x, y := vm.stack.Popn() vm.mem[x.String()] = y case oSLOAD: // Load the value in storage and push it on the stack x := vm.stack.Pop() // decode the object as a big integer decoder := contract.Addr(x.Bytes()) if !decoder.IsNil() { vm.stack.Push(decoder.BigInt()) } else { vm.stack.Push(ethutil.BigFalse) } case oSSTORE: // Store Y at index X y, x := vm.stack.Popn() addr := ethutil.BigToBytes(x, 256) fmt.Printf(" => %x (%v) @ %v", y.Bytes(), y, ethutil.BigD(addr)) contract.SetAddr(addr, y) //contract.State().Update(string(idx), string(y)) case oJMP: x := int(vm.stack.Pop().Uint64()) // Set pc to x - 1 (minus one so the incrementing at the end won't effect it) pc = x pc-- case oJMPI: x := vm.stack.Pop() // Set pc to x if it's non zero if x.Cmp(ethutil.BigFalse) != 0 { pc = int(x.Uint64()) pc-- } case oIND: vm.stack.Push(big.NewInt(int64(pc))) case oEXTRO: memAddr := vm.stack.Pop() contractAddr := vm.stack.Pop().Bytes() // Push the contract's memory on to the stack vm.stack.Push(contractMemory(state, contractAddr, memAddr)) case oBALANCE: // Pushes the balance of the popped value on to the stack account := state.GetAccount(vm.stack.Pop().Bytes()) vm.stack.Push(account.Amount) case oMKTX: addr, value := vm.stack.Popn() from, length := vm.stack.Popn() makeInlineTx(addr.Bytes(), value, from, length, contract, state) case oSUICIDE: recAddr := vm.stack.Pop().Bytes() // Purge all memory deletedMemory := contract.state.Purge() // Add refunds to the pop'ed address refund := new(big.Int).Mul(StoreFee, big.NewInt(int64(deletedMemory))) account := state.GetAccount(recAddr) account.Amount.Add(account.Amount, refund) // Update the refunding address state.UpdateAccount(recAddr, account) // Delete the contract state.trie.Update(string(addr), "") ethutil.Config.Log.Debugf("(%d) => %x\n", deletedMemory, recAddr) break out default: fmt.Printf("Invalid OPCODE: %x\n", op) } ethutil.Config.Log.Debugln("") //vm.stack.Print() pc++ } state.UpdateContract(addr, contract) }
// evaluatePostfix takes a postfix expression and evaluates it func evaluatePostfix(postfix []string) (*big.Rat, error) { var stack stack.Stack result := new(big.Rat) // note: a new(big.Rat) has value "0/1" ie zero for _, token := range postfix { if isOperand(token) { bigrat := new(big.Rat) if _, err := fmt.Sscan(token, bigrat); err != nil { return nil, fmt.Errorf("unable to scan %s", token) } stack.Push(bigrat) } else if isOperator(token) { op2, err2 := stack.Pop() if err2 != nil { return nil, err2 } var op1 interface{} if token != "@" { var err1 error if op1, err1 = stack.Pop(); err1 != nil { return nil, err1 } } dummy := new(big.Rat) switch token { case "**": float1 := BigratToFloat(op1.(*big.Rat)) float2 := BigratToFloat(op2.(*big.Rat)) float_result := math.Pow(float1, float2) stack.Push(FloatToBigrat(float_result)) case "*": result := dummy.Mul(op1.(*big.Rat), op2.(*big.Rat)) stack.Push(result) case "/": result := dummy.Quo(op1.(*big.Rat), op2.(*big.Rat)) stack.Push(result) case "+": result = dummy.Add(op1.(*big.Rat), op2.(*big.Rat)) stack.Push(result) case "-": result = dummy.Sub(op1.(*big.Rat), op2.(*big.Rat)) stack.Push(result) case "<": if op1.(*big.Rat).Cmp(op2.(*big.Rat)) <= -1 { stack.Push(big.NewRat(1, 1)) } else { stack.Push(new(big.Rat)) } case ">": if op1.(*big.Rat).Cmp(op2.(*big.Rat)) >= 1 { stack.Push(big.NewRat(1, 1)) } else { stack.Push(new(big.Rat)) } case "@": result := dummy.Mul(big.NewRat(-1, 1), op2.(*big.Rat)) stack.Push(result) } } else { return nil, fmt.Errorf("unknown token %v", token) } } retval, err := stack.Pop() if err != nil { return nil, err } return retval.(*big.Rat), nil }
// BinaryOp returns the result of the binary expression x op y. // The operation must be defined for the operands. // To force integer division of Int operands, use op == token.QUO_ASSIGN // instead of token.QUO; the result is guaranteed to be Int in this case. // Division by zero leads to a run-time panic. // func BinaryOp(x Value, op token.Token, y Value) Value { x, y = match(x, y) switch x := x.(type) { case unknownVal: return x case boolVal: y := y.(boolVal) switch op { case token.LAND: return x && y case token.LOR: return x || y } case int64Val: a := int64(x) b := int64(y.(int64Val)) var c int64 switch op { case token.ADD: if !is63bit(a) || !is63bit(b) { return normInt(new(big.Int).Add(big.NewInt(a), big.NewInt(b))) } c = a + b case token.SUB: if !is63bit(a) || !is63bit(b) { return normInt(new(big.Int).Sub(big.NewInt(a), big.NewInt(b))) } c = a - b case token.MUL: if !is32bit(a) || !is32bit(b) { return normInt(new(big.Int).Mul(big.NewInt(a), big.NewInt(b))) } c = a * b case token.QUO: return normFloat(new(big.Rat).SetFrac(big.NewInt(a), big.NewInt(b))) case token.QUO_ASSIGN: // force integer division c = a / b case token.REM: c = a % b case token.AND: c = a & b case token.OR: c = a | b case token.XOR: c = a ^ b case token.AND_NOT: c = a &^ b default: goto Error } return int64Val(c) case intVal: a := x.val b := y.(intVal).val var c big.Int switch op { case token.ADD: c.Add(a, b) case token.SUB: c.Sub(a, b) case token.MUL: c.Mul(a, b) case token.QUO: return normFloat(new(big.Rat).SetFrac(a, b)) case token.QUO_ASSIGN: // force integer division c.Quo(a, b) case token.REM: c.Rem(a, b) case token.AND: c.And(a, b) case token.OR: c.Or(a, b) case token.XOR: c.Xor(a, b) case token.AND_NOT: c.AndNot(a, b) default: goto Error } return normInt(&c) case floatVal: a := x.val b := y.(floatVal).val var c big.Rat switch op { case token.ADD: c.Add(a, b) case token.SUB: c.Sub(a, b) case token.MUL: c.Mul(a, b) case token.QUO: c.Quo(a, b) default: goto Error } return normFloat(&c) case complexVal: y := y.(complexVal) a, b := x.re, x.im c, d := y.re, y.im var re, im big.Rat switch op { case token.ADD: // (a+c) + i(b+d) re.Add(a, c) im.Add(b, d) case token.SUB: // (a-c) + i(b-d) re.Sub(a, c) im.Sub(b, d) case token.MUL: // (ac-bd) + i(bc+ad) var ac, bd, bc, ad big.Rat ac.Mul(a, c) bd.Mul(b, d) bc.Mul(b, c) ad.Mul(a, d) re.Sub(&ac, &bd) im.Add(&bc, &ad) case token.QUO: // (ac+bd)/s + i(bc-ad)/s, with s = cc + dd var ac, bd, bc, ad, s, cc, dd big.Rat ac.Mul(a, c) bd.Mul(b, d) bc.Mul(b, c) ad.Mul(a, d) cc.Mul(c, c) dd.Mul(d, d) s.Add(&cc, &dd) re.Add(&ac, &bd) re.Quo(&re, &s) im.Sub(&bc, &ad) im.Quo(&im, &s) default: goto Error } return normComplex(&re, &im) case stringVal: if op == token.ADD { return x + y.(stringVal) } } Error: panic(fmt.Sprintf("invalid binary operation %v %s %v", x, op, y)) }
func Quotient(a, b *big.Rat) big.Rat { var q big.Rat return Minus(*q.Quo(a, b)) }
func backsub(m Matrix) (Vector, error) { if len(m) == 0 || len(m[0]) < 2 { return Vector{}, nil } coeffs := make(Vector, len(m[0])-1) cnts := make([]int, len(m)) for i := range cnts { cnts[i] = -1 } zero := new(big.Rat) for i := range m { nz := 0 l := len(m[i]) - 1 for j := range m[i][:l] { if m[i][j].Cmp(zero) != 0 { nz++ } } if l-nz == l { return nil, fmt.Errorf("contains a zero row") } cnts[i] = nz } z := make([]index, len(cnts)) for i := range z { z[i].r = i z[i].n = cnts[i] } sort.Sort(indexSlice(z)) for i := range z { r := m[z[i].r] l := len(r) - 1 w := new(big.Rat).Set(r[l]) var v *big.Rat for j := range r[:l] { if r[j].Cmp(zero) == 0 { continue } if coeffs[j] != nil { u := new(big.Rat).Set(coeffs[j]) u.Mul(u, r[j]) w.Sub(w, u) } else if v != nil { return nil, fmt.Errorf("matrix not in rref form") } else { v = new(big.Rat).Set(r[j]) } } if v.Cmp(zero) == 0 { return nil, fmt.Errorf("matrix not in rref form") } coeffs[z[i].r] = w.Quo(w, v) } return coeffs, nil }