// Match attempts to match the internal constant representations of x and y. // If the attempt is successful, the result is the values of x and y, // if necessary converted to have the same internal representation; otherwise // the results are invalid. func (x Const) Match(y Const) (u, v Const) { switch a := x.val.(type) { case bool: if _, ok := y.val.(bool); ok { u, v = x, y } case *big.Int: switch y.val.(type) { case *big.Int: u, v = x, y case *big.Rat: var z big.Rat z.SetInt(a) u, v = Const{&z}, y case cmplx: var z big.Rat z.SetInt(a) u, v = Const{cmplx{&z, big.NewRat(0, 1)}}, y } case *big.Rat: switch y.val.(type) { case *big.Int: v, u = y.Match(x) case *big.Rat: u, v = x, y case cmplx: u, v = Const{cmplx{a, big.NewRat(0, 0)}}, y } case cmplx: switch y.val.(type) { case *big.Int, *big.Rat: v, u = y.Match(x) case cmplx: u, v = x, y } case string: if _, ok := y.val.(string); ok { u, v = x, y } default: panic("unreachable") } return }
func split(turn, maxTurns int, blueDiscsDrawn int, current, result *big.Rat) { if blueDiscsDrawn > (maxTurns / 2) { result.Add(result, current) //fmt.Println(blueDiscsDrawn, current) return } else if turn > maxTurns { return } redCurrent := big.NewRat(1, 1) blueCurrent := big.NewRat(1, 1) redCurrent.Mul(current, big.NewRat(int64(turn), int64(turn+1))) blueCurrent.Mul(current, big.NewRat(1, int64(turn+1))) split(turn+1, maxTurns, blueDiscsDrawn, redCurrent, result) split(turn+1, maxTurns, blueDiscsDrawn+1, blueCurrent, result) }
// MakeConst makes an ideal constant from a literal // token and the corresponding literal string. func MakeConst(tok token.Token, lit string) Const { switch tok { case token.INT: var x big.Int _, ok := x.SetString(lit, 0) assert(ok) return Const{&x} case token.FLOAT: var y big.Rat _, ok := y.SetString(lit) assert(ok) return Const{&y} case token.IMAG: assert(lit[len(lit)-1] == 'i') var im big.Rat _, ok := im.SetString(lit[0 : len(lit)-1]) assert(ok) return Const{cmplx{big.NewRat(0, 1), &im}} case token.CHAR: assert(lit[0] == '\'' && lit[len(lit)-1] == '\'') code, _, _, err := strconv.UnquoteChar(lit[1:len(lit)-1], '\'') assert(err == nil) return Const{big.NewInt(int64(code))} case token.STRING: s, err := strconv.Unquote(lit) assert(err == nil) return Const{s} } panic("unreachable") }
func assertProb(t *T, b *Bayesian, expected *big.Rat, word string) { actual := b.ProbAWhenB(word) if expected.Cmp(actual) != 0 { t.Errorf("'%s' should be correlated %v:%v with Grinnell tweets, but was %v:%v\n", word, expected.Num(), expected.Denom(), actual.Num(), actual.Denom()) } }
// a.convertTo(t) converts the value of the analyzed expression a, // which must be a constant, ideal number, to a new analyzed // expression with a constant value of type t. // // TODO(austin) Rename to resolveIdeal or something? func (a *expr) convertTo(t Type) *expr { if !a.t.isIdeal() { log.Panicf("attempted to convert from %v, expected ideal", a.t) } var rat *big.Rat // XXX(Spec) The spec says "It is erroneous". // // It is an error to assign a value with a non-zero fractional // part to an integer, or if the assignment would overflow or // underflow, or in general if the value cannot be represented // by the type of the variable. switch a.t { case IdealFloatType: rat = a.asIdealFloat()() if t.isInteger() && !rat.IsInt() { a.diag("constant %v truncated to integer", rat.FloatString(6)) return nil } case IdealIntType: i := a.asIdealInt()() rat = new(big.Rat).SetInt(i) default: log.Panicf("unexpected ideal type %v", a.t) } // Check bounds if t, ok := t.lit().(BoundedType); ok { if rat.Cmp(t.minVal()) < 0 { a.diag("constant %v underflows %v", rat.FloatString(6), t) return nil } if rat.Cmp(t.maxVal()) > 0 { a.diag("constant %v overflows %v", rat.FloatString(6), t) return nil } } // Convert rat to type t. res := a.newExpr(t, a.desc) switch t := t.lit().(type) { case *uintType: n, d := rat.Num(), rat.Denom() f := new(big.Int).Quo(n, d) f = f.Abs(f) v := uint64(f.Int64()) res.eval = func(*Thread) uint64 { return v } case *intType: n, d := rat.Num(), rat.Denom() f := new(big.Int).Quo(n, d) v := f.Int64() res.eval = func(*Thread) int64 { return v } case *idealIntType: n, d := rat.Num(), rat.Denom() f := new(big.Int).Quo(n, d) res.eval = func() *big.Int { return f } case *floatType: n, d := rat.Num(), rat.Denom() v := float64(n.Int64()) / float64(d.Int64()) res.eval = func(*Thread) float64 { return v } case *idealFloatType: res.eval = func() *big.Rat { return rat } default: log.Panicf("cannot convert to type %T", t) } return res }
func simpRat(x *big.Rat) Obj { if x.Denom().Cmp(one_Int) == 0 { return simpBig(x.Num()) } return wrap(x) }
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") }
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") }