• Russ Cox's avatar
    math: fix Gamma(x) for x < -170.5 and other corner cases · a39920fd
    Russ Cox authored
    Fixes #11441.
    
    Test tables generated by
    
    	package main
    
    	import (
    		"bytes"
    		"fmt"
    		"log"
    		"os/exec"
    		"strconv"
    		"strings"
    	)
    
    	var inputs = []float64{
    		0.5,
    		1.5,
    		2.5,
    		3.5,
    		-0.5,
    		-1.5,
    		-2.5,
    		-3.5,
    		0.1,
    		0.01,
    		1e-8,
    		1e-16,
    		1e-3,
    		1e-16,
    		1e-308,
    		5.6e-309,
    		5.5e-309,
    		1e-309,
    		1e-323,
    		5e-324,
    		-0.1,
    		-0.01,
    		-1e-8,
    		-1e-16,
    		-1e-3,
    		-1e-16,
    		-1e-308,
    		-5.6e-309,
    		-5.5e-309,
    		-1e-300 / 1e9,
    		-1e-300 / 1e23,
    		-5e-300 / 1e24,
    		-0.9999999999999999,
    		-1.0000000000000002,
    		-1.9999999999999998,
    		-2.0000000000000004,
    		-100.00000000000001,
    		-99.999999999999986,
    		17,
    		171,
    		171.6,
    		171.624,
    		171.625,
    		172,
    		2000,
    		-100.5,
    		-160.5,
    		-170.5,
    		-171.5,
    		-176.5,
    		-177.5,
    		-178.5,
    		-179.5,
    		-201.0001,
    		-202.9999,
    		-1000.5,
    		-1000000000.3,
    		-4503599627370495.5,
    		-63.349078729022985,
    		-127.45117632943295,
    	}
    
    	func main() {
    		var buf bytes.Buffer
    		for _, v := range inputs {
    			fmt.Fprintf(&buf, "gamma(%.1000g)\n", v)
    		}
    		cmd := exec.Command("gp", "-q")
    		cmd.Stdin = &buf
    		out, err := cmd.CombinedOutput()
    		if err != nil {
    			log.Fatalf("gp: %v", err)
    		}
    		f := strings.Split(string(out), "\n")
    		if len(f) > 0 && f[len(f)-1] == "" {
    			f = f[:len(f)-1]
    		}
    		if len(f) != len(inputs) {
    			log.Fatalf("gp: wrong output count\n%s\n", out)
    		}
    		for i, g := range f {
    			gf, err := strconv.ParseFloat(strings.Replace(g, " E", "e", -1), 64)
    			if err != nil {
    				if strings.Contains(err.Error(), "value out of range") {
    					if strings.HasPrefix(g, "-") {
    						fmt.Printf("\t{%g, Inf(-1)},\n", inputs[i])
    					} else {
    						fmt.Printf("\t{%g, Inf(1)},\n", inputs[i])
    					}
    					continue
    				}
    				log.Fatal(err)
    			}
    			if gf == 0 && strings.HasPrefix(g, "-") {
    				fmt.Printf("\t{%g, Copysign(0, -1)},\n", inputs[i])
    				continue
    			}
    			fmt.Printf("\t{%g, %g},\n", inputs[i], gf)
    		}
    	}
    
    Change-Id: Ie98c7751d92b8ffb40e8313f5ea10df0890e2feb
    Reviewed-on: https://go-review.googlesource.com/30146
    Run-TryBot: Russ Cox <rsc@golang.org>
    Reviewed-by: 's avatarQuentin Smith <quentin@golang.org>
    a39920fd
gamma.go 5 KB