// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build ignore

package main

import (
	"bytes"
	"fmt"
	"go/format"
	"log"
	"math/big"
	"os"
)

const (
	minExp = -348
	maxExp = 347
)

func main() {
	log.SetPrefix("pow10gen: ")
	log.SetFlags(0)

	var (
		one = big.NewInt(1)
		ten = big.NewInt(10)

		b1p64  = new(big.Int).Lsh(one, 64)
		b1p128 = new(big.Int).Lsh(one, 128)

		r2     = big.NewRat(2, 1)
		r1p128 = new(big.Rat).SetInt(b1p128)
	)

	var out bytes.Buffer
	fmt.Fprintf(&out, top, minExp, maxExp)
	for e := int64(minExp); e <= maxExp; e++ {
		var r *big.Rat
		if e >= 0 {
			r = new(big.Rat).SetInt(new(big.Int).Exp(ten, big.NewInt(e), nil))
		} else {
			r = new(big.Rat).SetFrac(one, new(big.Int).Exp(ten, big.NewInt(-e), nil))
		}
		be := 0
		for r.Cmp(r1p128) < 0 {
			r.Mul(r, r2)
			be++
		}
		for r.Cmp(r1p128) >= 0 {
			r.Quo(r, r2)
			be--
		}
		d := new(big.Int).Div(r.Num(), r.Denom())
		hi, lo := new(big.Int).DivMod(d, b1p64, new(big.Int))
		uhi := hi.Uint64()
		ulo := lo.Uint64()
		if !r.IsInt() {
			ulo++
			if ulo == 0 {
				uhi++
			}
		}
		if ulo != 0 {
			uhi++
			ulo = -ulo
		}
		fmt.Fprintf(&out, "\t{%#016x, %#016x}, // 1e%d * 2**%d\n", uhi, ulo, e, be)
	}
	fmt.Fprintf(&out, "}\n")

	src, err := format.Source(out.Bytes())
	if err != nil {
		log.Fatal(err)
	}

	if err := os.WriteFile("pow10tab.go", src, 0666); err != nil {
		log.Fatal(err)
	}
}

var top = `// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Code generated by: go run pow10gen.go. DO NOT EDIT.
//
//go:generate go run pow10gen.go

package strconv

const (
	pow10Min = %d
	pow10Max = %d
)


// pow10Tab holds 128-bit mantissas of powers of 10.
// The values are scaled so the high bit is always set.
var pow10Tab = [...]pmHiLo{
`
