Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dectest suite and regex parser #18

Merged
merged 63 commits into from
Feb 11, 2019
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
46e10fa
added some tests
joshcarp Jan 5, 2019
ef4cfde
Merge remote-tracking branch 'upstream/master'
joshcarp Jan 5, 2019
30652eb
Overflow protection, rounding to inf in Add function
joshcarp Jan 6, 2019
69f54ee
Overflow protection, rounding to inf in Add function
joshcarp Jan 6, 2019
ed16296
fixed problems with last pull request
joshcarp Jan 7, 2019
a4ba143
cleaned up tests
joshcarp Jan 7, 2019
9e8c835
fix Quo function div by zero
joshcarp Jan 8, 2019
bdafc16
fix Mul function infinities
joshcarp Jan 8, 2019
b4d7d8e
edit newFromParts to return infinity
joshcarp Jan 9, 2019
7a9ecee
Edit style and test for infinity
joshcarp Jan 9, 2019
fdc99ad
fix newfromparts sum of zero and small numbers into big
joshcarp Jan 10, 2019
73aeca3
Fix pull request based off feedback in #14
joshcarp Jan 22, 2019
69a33ba
Fix global variable comment
joshcarp Jan 22, 2019
fab891a
Move overflow protection to NewfromParts from arithmetic functions
joshcarp Jan 22, 2019
4afa09c
Simplify newFromParts, inf protection moved to arithmetic functions
joshcarp Jan 23, 2019
ddcd461
Fix blank line
joshcarp Jan 23, 2019
c6bf77c
Add dectest suite and regex parser
joshcarp Jan 31, 2019
5089e90
Add comments on test suite functions
joshcarp Jan 31, 2019
715e5b2
Fix Comment and simplify regex
joshcarp Feb 1, 2019
6d6ae90
Add structs for testcases, Delete error function
joshcarp Feb 1, 2019
b9cf37e
Fix regex; inlone comments, simplify for loop
joshcarp Feb 2, 2019
746aa74
Change boolean variable to testFailed in doTests, use Cmp function
joshcarp Feb 2, 2019
e566925
Fix TODOs in doTest
joshcarp Feb 2, 2019
c857c2f
Use prettier syntax for stuct assignment in getInput
joshcarp Feb 2, 2019
7b16d48
Fix unnecessary local variables in math unit tests
joshcarp Feb 2, 2019
79697d1
fix maxSig global constant
joshcarp Feb 2, 2019
ddbbd67
fix newline
joshcarp Feb 2, 2019
95fc7b1
Merge branch 'master' into master
joshcarp Feb 2, 2019
aa5a0a6
Add parseResult struct
joshcarp Feb 2, 2019
92df92e
Merge branch 'master' of https://github.com/Joshcarp/decimal
joshcarp Feb 2, 2019
d776a2e
Fix blanklines and newlines
joshcarp Feb 2, 2019
0010a7b
Revert to == from cmp until Cmp function gets fixed
joshcarp Feb 2, 2019
cf5f456
revert the revert and fix assignment to struct dec64Vals
joshcarp Feb 2, 2019
0a8f3a8
Add .gitattributes
joshcarp Feb 2, 2019
a505f0f
Fix regex to non capturing groups
joshcarp Feb 3, 2019
e038d25
fix TODO in testfromsuite
joshcarp Feb 3, 2019
b1c589c
Change TODO in testfromsuite
joshcarp Feb 3, 2019
ea49b5b
Make .gitattributes linguist-vendored to true
joshcarp Feb 3, 2019
a46a8b3
fix .gitattributes whitespaces
joshcarp Feb 3, 2019
7a36606
Edit capture names in regex string
joshcarp Feb 3, 2019
d0b0336
change variable names
joshcarp Feb 3, 2019
110d225
Add specific function for operations to return Decimal64
joshcarp Feb 3, 2019
9f870c8
Add more functions in execOp
joshcarp Feb 4, 2019
a26c3f8
Fix test file reading
joshcarp Feb 4, 2019
3e25e30
Fix double bracket around regex
joshcarp Feb 4, 2019
113d9ba
Fix comments
joshcarp Feb 4, 2019
fac572e
Change TestFailed to TestPassed, fix newlines
joshcarp Feb 4, 2019
b03666d
Fix more parentheses
joshcarp Feb 4, 2019
52644f3
fix comma
joshcarp Feb 5, 2019
8c8d098
Implement error returns in decimalSuite_test
joshcarp Feb 6, 2019
1b20b89
change .gitattributes linguist-vendored=true to linguist-vendored
joshcarp Feb 6, 2019
968473a
fix constant
joshcarp Feb 6, 2019
226aa4b
Fix variable names in suite_test
joshcarp Feb 6, 2019
2e18496
change panic in execOp
joshcarp Feb 6, 2019
894004c
fix error printing
joshcarp Feb 6, 2019
74923fc
Simplify parsing error into one error, depreciated parseResult struct
joshcarp Feb 6, 2019
5b610c4
Fix error messages
joshcarp Feb 6, 2019
2a0d599
Comment out TestFromSuite, failing tests will be fixed in next PR
joshcarp Feb 7, 2019
1b734d6
Fix Comments
joshcarp Feb 7, 2019
a8ef27c
Fix variable names and return statement
joshcarp Feb 7, 2019
53c992e
Fix constant comment
joshcarp Feb 7, 2019
e18df39
Fix for loop
joshcarp Feb 7, 2019
2c5c43a
Move .gitattributes
joshcarp Feb 7, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions decimal64.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ func matchScales(exp1 int, significand1 uint64, exp2 int, significand2 uint64) (

func newFromParts(sign int, exp int, significand uint64) Decimal64 {
s := uint64(sign) << 63

joshcarp marked this conversation as resolved.
Show resolved Hide resolved
if significand < 0x8<<50 {
// s EEeeeeeeee (0)ttt tttttttttt tttttttttt tttttttttt tttttttttt tttttttttt
// EE ∈ {00, 01, 10}
Expand Down
3 changes: 1 addition & 2 deletions decimal64_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package decimal

import (
"github.com/stretchr/testify/require"
"math"
"testing"

"github.com/stretchr/testify/require"
joshcarp marked this conversation as resolved.
Show resolved Hide resolved
)

func TestNew64FromInt64(t *testing.T) {
Expand Down
9 changes: 9 additions & 0 deletions decimal64const.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,17 @@ var inf64 uint64 = 0x78 << 56
// 1E15
const decimal64Base = 1000 * 1000 * 1000 * 1000 * 1000

// Max significand possible (16 decimal places)
const maxSig = decimal64Base*10 - 1
joshcarp marked this conversation as resolved.
Show resolved Hide resolved

const expOffset = 398
const expMax = 369

// Max64 is max number possible with Decimal64
var Max64 = newFromParts(0, expMax, maxSig)

// Min64 is minimum number that is subnormal possible with Decimal64
var Min64 = newFromParts(0, -398, 1)

var zeroes = []Decimal64{Zero64, NegZero64}
var infinities = []Decimal64{Infinity64, NegInfinity64}
29 changes: 19 additions & 10 deletions decimal64math.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,17 @@ func (d Decimal64) Add(e Decimal64) Decimal64 {
}
return QNaN64
}
if significand1 == 0 && significand2 == 0 {
return Zero64
}

exp1, significand1, exp2, significand2 = matchScales(exp1, significand1, exp2, significand2)

if sign1 == sign2 {
significand := significand1 + significand2
if significand >= decimal64Base {
exp1++
significand /= 10
exp1, significand = renormalize(exp1, significand)
if significand > maxSig || exp1 > expMax {
return infinities[sign1]
}
return newFromParts(sign1, exp1, significand)
}
Expand Down Expand Up @@ -91,11 +96,10 @@ func (d Decimal64) Mul(e Decimal64) Decimal64 {

exp := exp1 + exp2 + 15
significand := umul64(significand1, significand2).div64(decimal64Base)
for significand.lo >= 10*decimal64Base {
exp++
significand.lo /= 10
exp, significand.lo = renormalize(exp, significand.lo)
if significand.lo > maxSig || exp > expMax {
return infinities[sign]
}

return newFromParts(sign, exp, significand.lo)
}

Expand Down Expand Up @@ -133,12 +137,17 @@ func (d Decimal64) Quo(e Decimal64) Decimal64 {
return zeroes[sign]
}

if e == Zero64 || e == NegZero64 {
return infinities[sign1]
}

exp := exp1 - exp2 - 16
significand := umul64(10*decimal64Base, significand1).div64(significand2)
for significand.hi > 0 || significand.lo >= 10*decimal64Base {
exp++
significand = significand.divBy10()
exp, significand.lo = renormalize(exp, significand.lo)
if significand.lo > maxSig || exp > expMax {
return infinities[sign]
}

return newFromParts(sign, exp, significand.lo)
}

Expand Down
41 changes: 41 additions & 0 deletions decimal64math_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -379,3 +379,44 @@ func BenchmarkDecimal64Sub(b *testing.B) {
_ = x[i%len(x)].Sub(y[i%len(y)])
}
}

func TestAddOverflow(t *testing.T) {
require := require.New(t)

a := MustParseDecimal64("-9.999999999999999e384")
require.Equal(NegInfinity64, a.Sub(MustParseDecimal64("0.00000000000001e384")))
a = Max64
joshcarp marked this conversation as resolved.
Show resolved Hide resolved
require.Equal(Infinity64, a.Add(MustParseDecimal64("0.000000000000001e384")))
require.Equal(a, a.Add(MustParseDecimal64("1")))
require.Equal(a, Zero64.Add(a))
}

func TestQuoOverflow(t *testing.T) {
require := require.New(t)

a := MustParseDecimal64("1e384")
require.Equal(Infinity64, a.Quo(MustParseDecimal64(".01")))
a = MustParseDecimal64("1e384")
require.Equal(NegInfinity64, a.Quo(MustParseDecimal64("-.01")))
a = MustParseDecimal64("-1e384")
require.Equal(NegInfinity64, a.Quo(MustParseDecimal64(".01")))
a = MustParseDecimal64("-1e384")
require.Equal(NegInfinity64, a.Quo(MustParseDecimal64("0")))
require.Equal(QNaN64, Zero64.Quo(Zero64))
require.Equal(Zero64, Zero64.Quo(MustParseDecimal64("100")))
}

func TestMul(t *testing.T) {
require := require.New(t)

a := MustParseDecimal64("1e384")
require.Equal(Infinity64, a.Mul(MustParseDecimal64("10")))
a = MustParseDecimal64("1e384")
require.Equal(NegInfinity64, a.Mul(MustParseDecimal64("-10")))
a = MustParseDecimal64("-1e384")
require.Equal(NegInfinity64, a.Mul(MustParseDecimal64("10")))
a = MustParseDecimal64("-1e384")
require.Equal(NegZero64, a.Mul(Zero64))
require.Equal(Zero64, Zero64.Mul(Zero64))
require.Equal(Zero64, Zero64.Mul(MustParseDecimal64("100")))
}
138 changes: 138 additions & 0 deletions decimalSuite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package decimal

import (
"fmt"
"io/ioutil"
"regexp"
"strings"
"testing"
)

// master tester for the suite
func TestFromSuite(t *testing.T) {
// require := require.New(t)
joshcarp marked this conversation as resolved.
Show resolved Hide resolved
testVals, testNames := getInput("dectest/ddAdd.decTest")

var testName string
var TestResult string
joshcarp marked this conversation as resolved.
Show resolved Hide resolved
var TestPass bool
var testVal1, testVal2, testAns Decimal64
var parseResult string

for i := range testNames {
testName = testNames[i]
testVal1, testVal2, testAns, parseResult = convertToDec64(testVals[testName], testName)
TestPass, TestResult = doTests(testVal1, testVal2, testAns, testVals[testName]["TestFunc"])
if TestPass == false {
fmt.Printf("%s: \n %s\n %s\n", testName, TestResult, parseResult)
}
}

}

// func TestNew(t *testing.T) {
joshcarp marked this conversation as resolved.
Show resolved Hide resolved
// // require := require.New(t)
// // // propper rounding
// // require.Equal(MustParseDecimal64("4444444444444445"), MustParseDecimal64("4444444444444444").Add(MustParseDecimal64("0.5001")))
// // require.Equal(MustParseDecimal64("0.23"), MustParseDecimal64("1.3").Add(MustParseDecimal64("-1.07")))
// // fmt.Println("sjoidgf", MustParseDecimal64("4444444444444444").Add(MustParseDecimal64("1.5001")))
// // // require.Equal(MustParseDecimal64("12345678901234.29"), MustParseDecimal64("12345678901234").Add(MustParseDecimal64("0.2951")))
//
// }

//getInput gets the test file and extracts test using regex, then returns a map object and a list of test names
func getInput(file string) (map[string]map[string]string, []string) {
joshcarp marked this conversation as resolved.
Show resolved Hide resolved
dat, _ := ioutil.ReadFile("dectest/ddAdd.decTest")
dataString := string(dat)
// "(\n|\r)") // start with newline
joshcarp marked this conversation as resolved.
Show resolved Hide resolved
// "(?P<TestName>dd[\w]*)") // TestName must start with dd (double decimal)
// "(?P<TestFunc>[\S]*)") // testfunc made of anything that isn't a whitespace
// "(\s*\'?)") // after can be any number of spaces and quotations if they exist
// "(?P<TestVals_1>(\+|-)*[^\r\n\t\f\v\' ]*)") // first test val is anything that isnt a whitespace or a quoteation mark
joshcarp marked this conversation as resolved.
Show resolved Hide resolved
// "(?P<TestVals_1>(\+|-)*[^\r\n\t\f\v\' ]*)") // first test val is anything that isnt a whitespace or a quoteation mark
// ('?\s*'?) match any quotation marks and any spaces
// (?P<TestVals_2>(\+|-[^->])?[^\r\n\t\f\v\' ]*) testvals2 same as 1 but no '->'
// ('?\s*->\s*'?) matches the indicator to answer
// (?P<answer>(\+|-)*[^\r\n\t\f\v\' ]*) matches the answer that's anything that is plus minus but not quotations

// split into groups: testName, TestFunct, TestVals (x2) and TestAns
regex := `(\n|\r)(?P<TestName>dd[\w]*)(\s*)(?P<TestFunc>[\S]*)(\s*\'?)(?P<TestVals_1>(\+|-)*[^\r\n\t\f\v\' ]*)('?\s*'?)(?P<TestVals_2>(\+|-[^->])?[^\r\n\t\f\v\' ]*)('?\s*->\s*'?)(?P<answer>(\+|-)*[^\r\n\t\f\v\' ]*)`
joshcarp marked this conversation as resolved.
Show resolved Hide resolved
r := regexp.MustCompile(regex)
ans := r.FindAllStringSubmatch(dataString, -1)
testList := []string{}
var data = map[string]map[string]string{}
joshcarp marked this conversation as resolved.
Show resolved Hide resolved

for i := 0; i < len(ans); i++ {
joshcarp marked this conversation as resolved.
Show resolved Hide resolved
data[ans[i][2]] = make(map[string]string)
data[ans[i][2]]["TestFunc"] = ans[i][4]
data[ans[i][2]]["TestVal1"] = ans[i][6]
data[ans[i][2]]["TestVal2"] = ans[i][9]
data[ans[i][2]]["TestAns"] = ans[i][12]
testList = append(testList, ans[i][2])

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary blank line

}
return data, testList

}

//convertToDec64 converts the map object strings to decimal64s
joshcarp marked this conversation as resolved.
Show resolved Hide resolved
func convertToDec64(testVals map[string]string, testName string) (testVal1, testVal2, testAns Decimal64, parseErr string) {
var err1, err2, err3 error
joshcarp marked this conversation as resolved.
Show resolved Hide resolved
// var TestResult []string

testVal1, err1 = ParseDecimal64(testVals["TestVal1"])
testAns, err3 = ParseDecimal64(testVals["TestAns"])

testVal2, err2 = ParseDecimal64(testVals["TestVal2"])
parseErr = checkErrors(err1, err2, err3, testVals)

return
}

//checkErrors checks to see if there are any string parsing errors
func checkErrors(err1, err2, err3 error, testVals map[string]string) (errReturn string) {
joshcarp marked this conversation as resolved.
Show resolved Hide resolved
var errReturnSlice []string
if err2 != nil {
errReturnSlice = append(errReturnSlice, fmt.Sprintf("error parsing input of value: %s \n", testVals["TestVal2"]))
}
if err1 != nil {
errReturnSlice = append(errReturnSlice, fmt.Sprintf("error parsing input of value: %s \n", testVals["TestVal1"]))
}

if err3 != nil {
errReturnSlice = append(errReturnSlice, fmt.Sprintf("error parsing input of value: %s \n", testVals["TestAns"]))
}
return strings.Join(errReturnSlice, "")
}

//doTests completes the tests and returns a boolean and string on if the test passes
joshcarp marked this conversation as resolved.
Show resolved Hide resolved
func doTests(testVal1, testVal2, testAns Decimal64, testfunc string) (testStatus bool, testString string) {
joshcarp marked this conversation as resolved.
Show resolved Hide resolved

fmt.Println()
joshcarp marked this conversation as resolved.
Show resolved Hide resolved
switch testfunc {
case "add":
testString = fmt.Sprintf("%v + %v != %v \n(expected %v)", testVal1, testVal2, testVal1.Add(testVal2), testAns)
testStatus = testAns == testVal1.Add(testVal2)
return
case "abs":

joshcarp marked this conversation as resolved.
Show resolved Hide resolved
testStatus = testAns == testVal1.Abs()
return
case "divide":

joshcarp marked this conversation as resolved.
Show resolved Hide resolved
testStatus = testAns == testVal1.Quo(testVal2)
return
case "minus":

joshcarp marked this conversation as resolved.
Show resolved Hide resolved
testStatus = testAns == testVal1.Sub(testVal2)
return
case "multiply":
testString = fmt.Sprintf("%v * %v != %v (expected %v)", testVal1, testVal2, testVal1.Mul(testVal2), testAns)
testStatus = testAns == testVal1.Mul(testVal2)
return
default:
testStatus = false
return
}

joshcarp marked this conversation as resolved.
Show resolved Hide resolved
}
Loading