func setBigIntString(conf *config.Config, s string) (BigInt, error) { i, ok := big.NewInt(0).SetString(s, conf.InputBase()) if !ok { return BigInt{}, errors.New("integer parse error") } return BigInt{i}, nil }
// printValues neatly prints the values returned from execution, followed by a newline. // It also handles the ')debug types' output. // The return value reports whether it printed anything. func printValues(conf *config.Config, writer io.Writer, values []value.Value) bool { if len(values) == 0 { return false } if conf.Debug("types") { for i, v := range values { if i > 0 { fmt.Fprint(writer, ",") } fmt.Fprintf(writer, "%T", v) } fmt.Fprintln(writer) } printed := false for _, v := range values { if _, ok := v.(parse.Assignment); ok { continue } s := v.Sprint(conf) if printed && len(s) > 0 && s[len(s)-1] != '\n' { fmt.Fprint(writer, " ") } fmt.Fprint(writer, s) printed = true } if printed { fmt.Fprintln(writer) } return printed }
func (i BigInt) Sprint(conf *config.Config) string { bitLen := i.BitLen() format := conf.Format() var maxBits = (uint64(conf.MaxDigits()) * 33222) / 10000 // log 10 / log 2 is 3.32192809489 if uint64(bitLen) > maxBits && maxBits != 0 { // Print in floating point. return BigFloat{newF(conf).SetInt(i.Int)}.Sprint(conf) } if format != "" { verb, prec, ok := conf.FloatFormat() if ok { return i.floatString(verb, prec) } return fmt.Sprintf(format, i.Int) } // Is this from a rational and we could use an int? if i.BitLen() < intBits { return Int(i.Int64()).Sprint(conf) } switch conf.OutputBase() { case 0, 10: return fmt.Sprintf("%d", i.Int) case 2: return fmt.Sprintf("%b", i.Int) case 8: return fmt.Sprintf("%o", i.Int) case 16: return fmt.Sprintf("%x", i.Int) } Errorf("can't print number in base %d (yet)", conf.OutputBase()) return "" }
// newLoop returns a new loop checker. The arguments are the name // of the function being evaluated, the argument to the function, and // the maximum number of iterations to perform before giving up. // The last number in terms of iterations per bit, so the caller can // ignore the precision setting. func newLoop(conf *config.Config, name string, x *big.Float, itersPerBit uint) *loop { return &loop{ name: name, arg: newF(conf).Set(x), maxIterations: 10 + uint64(itersPerBit*conf.FloatPrec()), prevZ: newF(conf), delta: newF(conf), prevDelta: newF(conf), } }
func (r BigRat) toType(conf *config.Config, which valueType) Value { switch which { case bigRatType: return r case bigFloatType: f := new(big.Float).SetPrec(conf.FloatPrec()).SetRat(r.Rat) return BigFloat{f} case vectorType: return NewVector([]Value{r}) case matrixType: return NewMatrix([]Value{one, one}, []Value{r}) } Errorf("cannot convert rational to %s", which) return nil }
func (i BigInt) toType(conf *config.Config, which valueType) Value { switch which { case bigIntType: return i case bigRatType: r := big.NewRat(0, 1).SetInt(i.Int) return BigRat{r} case bigFloatType: f := new(big.Float).SetPrec(conf.FloatPrec()).SetInt(i.Int) return BigFloat{f} case vectorType: return NewVector([]Value{i}) case matrixType: return NewMatrix([]Value{one}, []Value{i}) } Errorf("cannot convert big int to %s", which) return nil }
func (m Matrix) higherDim(conf *config.Config, prefix string, indentation int) string { if len(m.shape) <= 3 { return indent(indentation, m.Sprint(conf)) } dim := int(m.shape[0].(Int)) rest := strings.Repeat(" *", len(m.shape)-1)[1:] var b bytes.Buffer for i := 0; i < dim; i++ { inner := Matrix{ shape: m.shape[1:], data: m.data[i*m.elemSize():], } if i > 0 { b.WriteString("\n") } innerPrefix := fmt.Sprintf("%s%d ", prefix, i+conf.Origin()) b.WriteString(indent(indentation, "%s%s]:\n", innerPrefix, rest)) b.WriteString(inner.higherDim(conf, innerPrefix, indentation+1)) } return b.String() }
// printValues neatly prints the values returned from execution, followed by a newline. // It also handles the ')debug types' output. func printValues(conf *config.Config, writer io.Writer, values []value.Value) { if len(values) == 0 { return } if conf.Debug("types") { for i, v := range values { if i > 0 { fmt.Fprint(writer, ",") } fmt.Fprintf(writer, "%T", v) } fmt.Fprintln(writer) } for i, v := range values { s := v.Sprint(conf) if i > 0 && len(s) > 0 && s[len(s)-1] != '\n' { fmt.Fprint(writer, " ") } fmt.Fprint(writer, s) } fmt.Fprintln(writer) }
func (r BigRat) Sprint(conf *config.Config) string { format := conf.Format() if format != "" { verb, prec, ok := conf.FloatFormat() if ok { return r.floatString(verb, prec) } return fmt.Sprintf(conf.RatFormat(), r.Num(), r.Denom()) } num := BigInt{r.Num()} den := BigInt{r.Denom()} return fmt.Sprintf("%s/%s", num.Sprint(conf), den.Sprint(conf)) }
func (i Int) Sprint(conf *config.Config) string { format := conf.Format() if format != "" { verb, prec, ok := conf.FloatFormat() if ok { return i.floatString(verb, prec) } return fmt.Sprintf(format, int64(i)) } base := conf.OutputBase() if base == 0 { base = 10 } return strconv.FormatInt(int64(i), base) }
func setIntString(conf *config.Config, s string) (Int, error) { i, err := strconv.ParseInt(s, conf.InputBase(), intBits) return Int(i), err }
// save writes the state of the workspace to the named file. // The format of the output is ivy source text. func save(c *exec.Context, file string, conf *config.Config) { // "<conf.out>" is a special case for testing. out := conf.Output() if file != "<conf.out>" { fd, err := os.Create(file) if err != nil { value.Errorf("%s", err) } defer fd.Close() buf := bufio.NewWriter(fd) defer buf.Flush() out = buf } // Configuration settings. We will set the base below, // after we have printed all numbers in base 10. fmt.Fprintf(out, ")prec %d\n", conf.FloatPrec()) ibase, obase := conf.Base() fmt.Fprintf(out, ")maxbits %d\n", conf.MaxBits()) fmt.Fprintf(out, ")maxdigits %d\n", conf.MaxDigits()) fmt.Fprintf(out, ")origin %d\n", conf.Origin()) fmt.Fprintf(out, ")prompt %q\n", conf.Prompt()) fmt.Fprintf(out, ")format %q\n", conf.Format()) // Ops. printed := make(map[exec.OpDef]bool) for _, def := range c.Defs { var fn *exec.Function if def.IsBinary { fn = c.BinaryFn[def.Name] } else { fn = c.UnaryFn[def.Name] } for _, ref := range references(c, fn.Body) { if !printed[ref] { if ref.IsBinary { fmt.Fprintf(out, "op _ %s _\n", ref.Name) } else { fmt.Fprintf(out, "op %s _\n", ref.Name) } printed[ref] = true } } printed[def] = true fmt.Fprintln(out, fn) } // Global variables. syms := c.Stack[0] if len(syms) > 0 { // Set the base strictly to 10 for output. fmt.Fprintf(out, "# Set base 10 for parsing numbers.\n)base 10\n") // Sort the names for consistent output. sorted := sortSyms(syms) for _, sym := range sorted { // pi and e are generated if sym.name == "pi" || sym.name == "e" { continue } fmt.Fprintf(out, "%s = ", sym.name) put(out, sym.val) fmt.Fprint(out, "\n") } } // Now we can set the base. fmt.Fprintf(out, ")ibase %d\n", ibase) fmt.Fprintf(out, ")obase %d\n", obase) }
func newF(conf *config.Config) *big.Float { return new(big.Float).SetPrec(conf.FloatPrec()) }
func bigFloatInt64(conf *config.Config, x int64) BigFloat { return BigFloat{new(big.Float).SetPrec(conf.FloatPrec()).SetInt64(x)} }
func (f BigFloat) Sprint(conf *config.Config) string { var mant big.Float exp := f.Float.MantExp(&mant) positive := 1 if exp < 0 { positive = 0 exp = -exp } verb, prec := byte('g'), 12 format := conf.Format() if format != "" { v, p, ok := conf.FloatFormat() if ok { verb, prec = v, p } } // Printing huge floats can be very slow using // big.Float's native methods; see issue #11068. // For example 1e5000000 takes a minute of CPU time just // to print. The code below is instantaneous, by rescaling // first. It is however less feature-complete. // (Big ints are problematic too, but if you print 1e50000000 // as an integer you probably won't be surprised it's slow.) if fastFloatPrint && exp > 10000 { // We always use %g to print the fraction, and it will // never have an exponent, but if the format is %E we // need to use a capital E. eChar := 'e' if verb == 'E' || verb == 'G' { eChar = 'E' } fexp := newF(conf).SetInt64(int64(exp)) fexp.Mul(fexp, floatLog2) fexp.Quo(fexp, floatLog10) // We now have a floating-point base 10 exponent. // Break into the integer part and the fractional part. // The integer part is what we will show. // The 10**(fractional part) will be multiplied back in. iexp, _ := fexp.Int(nil) fraction := fexp.Sub(fexp, newF(conf).SetInt(iexp)) // Now compute 10**(fractional part). // Fraction is in base 10. Move it to base e. fraction.Mul(fraction, floatLog10) scale := exponential(conf, fraction) if positive > 0 { mant.Mul(&mant, scale) } else { mant.Quo(&mant, scale) } ten := newF(conf).SetInt64(10) i64exp := iexp.Int64() // For numbers not too far from one, print without the E notation. // Shouldn't happen (exp must be large to get here) but just // in case, we keep this around. if -4 <= i64exp && i64exp <= 11 { if i64exp > 0 { for i := 0; i < int(i64exp); i++ { mant.Mul(&mant, ten) } } else { for i := 0; i < int(-i64exp); i++ { mant.Quo(&mant, ten) } } return fmt.Sprintf("%g\n", &mant) } else { sign := "" if mant.Sign() < 0 { sign = "-" mant.Neg(&mant) } // If it has a leading zero, rescale. digits := mant.Text('g', prec) for digits[0] == '0' { mant.Mul(&mant, ten) if positive > 0 { i64exp-- } else { i64exp++ } digits = mant.Text('g', prec) } return fmt.Sprintf("%s%s%c%c%d", sign, digits, eChar, "-+"[positive], i64exp) } } return f.Float.Text(verb, prec) }
// mustFit errors out if n is larger than the maximum number of bits allowed. func mustFit(conf *config.Config, n int64) { max := conf.MaxBits() if max != 0 && n > int64(max) { Errorf("result too large (%d bits)", n) } }