// String returns a kind messy decimal string version of this. // It is utterly precise, and will use as many decimal digits // as are necessary to completely represent this number. func (f Float) String() string { sign := "+" if !f.sign { sign = "-" } var whole *mathx.Int var fraction *mathx.Int if f.exp <= 0 { whole = f.mantissa.Rsh(uint(-f.exp)) fraction = f.mantissa.Sub(whole.Lsh(uint(-f.exp))) } else { whole = mathx.NewInt(0) fraction = f.mantissa } whole = f.mantissa.Rsh(uint(-f.exp)) fraction = f.mantissa.Sub(whole.Lsh(uint(-f.exp))) digits := "" for fraction.Sign() != 0 { fraction = fraction.Mul64(10) digit := fraction.Rsh(uint(-f.exp)) fraction = fraction.Sub(digit.Lsh(uint(-f.exp))) digits += digit.String() } if digits == "" { digits = "0" } return fmt.Sprintf("%s%s.%s", sign, whole.String(), digits) }
func TestSqrt(t *testing.T) { numbers := []string{ "93845895110924997939619620205961794350920309182366517272043413179685324014761", "69105835870199153467162210945784416638855243478241804950569679288538869324319", "98962852285157630260915782241836609413140230175083651803312834404919437446053", "36317938229605222802428943032353131143116755641174816538429154625143871344197", "34350266504989669203432549294422599219204587184049128615381495990495502309209", "18204849169635358408169482661313928794336132815120732872856773352186520943781", "9723547989068653705018929505866149012335913222247343211073612173133525296219", "82871077872852450664782155632268023043996476167345573065229622315492882980623", "22856450670839904203062539524939514231429034860506554613939398064780917006117", "1133028424325951536479152017902354822905940331016138739712579674465852496751", "66190348295371735778910813271715110278762226582449603965856760126883910115231", "67110703748429597893338674661673279865284238141342172221809893325337357465213", "67907826904909216076322754184715993424884161760995928759256942503051716644171", "76128483155619054801182538439486844205442146012173793296249561612451294050669", "77820156304482546934043298147893054920197524209952870273345573570345100056869", "114580143581984719060280282563142542662414835420671277376461092447281111712587", } for _, numStr := range numbers { n, _ := mathx.NewIntFromString(numStr, 10) m := n.Sqrt() m1 := m.Add(mathx.NewInt(1)) if m.Mul(m).Cmp(n) >= 0 || m1.Mul(m1).Cmp(n) <= 0 { t.Errorf("Sqrt(%s) returned %s", n, m) } } }
// Discriminant returns the discriminant of this polynomial. func Discriminant(p *poly.IntPolynomial) *mathx.Int { if p.Degree() == 2 { c, b, a := p.Coeff(0), p.Coeff(1), p.Coeff(2) ac4 := mathx.NewInt(4).Mul(a).Mul(c) return b.Mul(b).Sub(ac4) } return nil }
func TestFundamentalDiscriminantsSmall(t *testing.T) { fundamentals := []int{1, 5, 8, 12, 13, 17, 21, 24, 28, 29, 33, -3, -4, -7, -8, -11, -15, -19, -20, -23, -24, -31} good := mathx.NewIntSet(fundamentals) for d := -31; d <= 33; d++ { a := IsFundamentalDiscriminant(mathx.NewInt(int64(d))) b := good.Contains(d) if a != b { t.Errorf("Fundamental discriminant failed for ", d) } } }
// NewFloat constructs a new Float from an IEEE 64-bit float64. func NewFloat(f float64) *Float { x := new(Float) x.precision = 52 // Convert from IEEE 754 double bits := math.Float64bits(f) s := bits >> 63 e := int64((bits >> 52) & 0x7ff) m := int64(bits & uint64((int64(1)<<52)-1)) if s == 0 && e == 0 && m == 0 { x.sign = false x.exp = 0 x.mantissa = mathx.NewInt(0) return x } if s == 0 { x.sign = true } x.exp = e - 1023 - 52 x.mantissa = mathx.NewInt((int64(1) << 52) | m) return x.normalize() }
func makeFundamentalDiscriminant(D int64) int64 { if IsFundamentalDiscriminant(mathx.NewInt(D)) { return D } factors := Factorization64(D) for _, f := range factors { ex := f.exponent for ex >= 2 { D = D / (f.prime * f.prime) ex -= 2 } } return D }
// IsIrreducible returns true if this polynomial is irreducible. // It currently only works on degree <= 2. func (p *IntPolynomial) IsIrreducible() bool { g := &p.coeffs[0] if g.Sign() == 0 { return false } // check the gcd of the coefficients for _, c := range p.coeffs { if c.Sign() == 0 { continue } g = g.GCD(&c) if g.Cmp(intOne) == 0 { break } } if g.Cmp(intOne) != 0 { return false } if p.Degree() == 1 { return true } if p.Degree() == 2 { c, b, a := p.coeffs[0], p.coeffs[1], p.coeffs[2] b2 := b.Mul(&b) ac4 := mathx.NewInt(4) ac4 = ac4.Mul(&a) ac4 = ac4.Mul(&c) b2 = b2.Sub(ac4) return !mathx.IsSquare((*mathx.Int)(b2)) } /* // check the gcd of the coefficients a0 := p.coeffs[0].Int64() g.SetInt64(a0) for i, c := range p.coeffs { if i == 0 { continue } if i == len(p.coeffs)-1 { break } if c.Sign() == 0 { continue } g.GCD(nil, nil, &g, &c) } if g.Cmp(intOne) != 0 { sufficient := true for _, primeExp := range Factorization64(g.Int64()) { p := primeExp.prime if a0%(p*p) == 0 { sufficient = false break } } if sufficient { return true } } */ // TODO: implement more cases return true }
// Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package poly import ( "strconv" "github.com/swenson/mathx" ) var intZero = mathx.NewInt(0) var intOne = mathx.NewInt(1) // IntPolynomial represents an integer polynomial of arbitrary size. type IntPolynomial struct { coeffs []mathx.Int } // NewIntPolynomial64 creates a new polynomial for the given // coefficients (assumed to be c0, c1, ...). func NewIntPolynomial64(coeffs ...int64) *IntPolynomial { p := new(IntPolynomial) p.coeffs = make([]mathx.Int, len(coeffs)) for i, c := range coeffs { p.coeffs[i] = *mathx.NewInt(c) }