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 all 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
11 changes: 7 additions & 4 deletions decimal64const.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,19 @@ var inf64 uint64 = 0x78 << 56
// 1E15
const decimal64Base = 1000 * 1000 * 1000 * 1000 * 1000

// Max significand possible (16 decimal places)
const maxSig = decimal64Base*10 - 1
// maxSig is the maximum significand possible that fits in 16 decimal places.
const maxSig = 10*decimal64Base - 1

anzdaddy marked this conversation as resolved.
Show resolved Hide resolved
const expOffset = 398
const expMax = 369

// Max64 is max number possible with Decimal64
// Max64 is the maximum number representable with a Decimal64.
var Max64 = newFromParts(0, expMax, maxSig)

// Min64 is minimum number that is subnormal possible with Decimal64
// NegMax64 is the minimum finite number (most negative) possible with Decimal64 (negative).
var NegMax64 = newFromParts(1, expMax, maxSig)
anzdaddy marked this conversation as resolved.
Show resolved Hide resolved

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

var zeroes = []Decimal64{Zero64, NegZero64}
Expand Down
37 changes: 12 additions & 25 deletions decimal64math_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -382,41 +382,28 @@ func BenchmarkDecimal64Sub(b *testing.B) {

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

a := MustParseDecimal64("-9.999999999999999e384")
require.Equal(NegInfinity64, a.Sub(MustParseDecimal64("0.00000000000001e384")))
a = Max64
require.Equal(Infinity64, a.Add(MustParseDecimal64("0.000000000000001e384")))
require.Equal(a, a.Add(MustParseDecimal64("1")))
require.Equal(a, Zero64.Add(a))
require.Equal(NegInfinity64, NegMax64.Sub(MustParseDecimal64("0.00000000000001e384")))
require.Equal(Infinity64, Max64.Add(MustParseDecimal64("0.000000000000001e384")))
require.Equal(Max64, Max64.Add(MustParseDecimal64("1")))
require.Equal(Max64, Zero64.Add(Max64))
}

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(Infinity64, MustParseDecimal64("1e384").Quo(MustParseDecimal64(".01")))
require.Equal(NegInfinity64, MustParseDecimal64("1e384").Quo(MustParseDecimal64("-.01")))
require.Equal(NegInfinity64, MustParseDecimal64("-1e384").Quo(MustParseDecimal64(".01")))
require.Equal(NegInfinity64, MustParseDecimal64("-1e384").Quo(MustParseDecimal64("0")))
anzdaddy marked this conversation as resolved.
Show resolved Hide resolved
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(Infinity64, MustParseDecimal64("1e384").Mul(MustParseDecimal64("10")))
require.Equal(NegInfinity64, MustParseDecimal64("1e384").Mul(MustParseDecimal64("-10")))
require.Equal(NegInfinity64, MustParseDecimal64("-1e384").Mul(MustParseDecimal64("10")))
require.Equal(NegZero64, MustParseDecimal64("-1e384").Mul(Zero64))
require.Equal(Zero64, Zero64.Mul(Zero64))
require.Equal(Zero64, Zero64.Mul(MustParseDecimal64("100")))
}
143 changes: 143 additions & 0 deletions decimalSuite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package decimal

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

type decValContainer struct {
joshcarp marked this conversation as resolved.
Show resolved Hide resolved
val1, val2, expected Decimal64
parseError error
}
type testCaseStrings struct {
testName string
testFunc string
val1 string
val2 string
expectedResult string
}

// TODO(joshcarp): This test cannot fail. Proper assertions will be added once the whole suite passes
// TestFromSuite is the master tester for the dectest suite.
// func TestFromSuite(t *testing.T) {
// testVals := getInput("dectest/ddAdd.decTest")
// for _, testVal := range testVals {
// dec64vals := convertToDec64(testVal)
// testErr := runTest(dec64vals, testVal)
// if testErr != nil {
// fmt.Println(testErr)
// }
// if dec64vals.parseError != nil {
// fmt.Println(dec64vals.parseError)
// }
// }
//
// }

// TODO: any tests that are failing a particular test in the test suite will be turned into a unit test.
// 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")))
//
// }

// TODO get regexto match with three inputs for functions like FMA.
// 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) (data []testCaseStrings) {
dat, _ := ioutil.ReadFile(file)
dataString := string(dat)
r := regexp.MustCompile(`(?:\n)` + // start with newline (?: non capturing group)
`(?P<testName>dd[\w]*)` + // first capturing group: testfunc made of anything that isn't a whitespace
`(?:\s*)` + // match any whitespace (?: non capturing group)
`(?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 (?: non capturing group)
`(?P<val1>\+?-?[^\t\f\v\' ]*)` + // first test val is anything that isnt a whitespace or a quoteation mark
`(?:'?\s*'?)` + // match any quotation marks and any space (?: non capturing group)
`(?P<val2>\+?-?[^->]?[^\t\f\v\' ]*)` + //testvals2 same as 1 but specifically dont match with '->'
`(?:'?\s*->\s*'?)` + // matches the indicator to answer and surrounding whitespaces (?: non capturing group)
`(?P<expectedResult>\+?-?[^\r\n\t\f\v\' ]*)`) // matches the answer that's anything that is plus minus but not quotations
joshcarp marked this conversation as resolved.
Show resolved Hide resolved
// capturing gorups are testName, testFunc, val1, val2, and expectedResult)
ans := r.FindAllStringSubmatch(dataString, -1)
for _, a := range ans {
data = append(data, testCaseStrings{
testName: a[1],
testFunc: a[2],
val1: a[3],
val2: a[4],
expectedResult: a[5],
})
}
return

}

// convertToDec64 converts the map object strings to decimal64s.
func convertToDec64(testvals testCaseStrings) (dec64vals decValContainer) {
var err1, err2, expectedErr error
dec64vals.val1, err1 = ParseDecimal64(testvals.val1)
dec64vals.val2, err2 = ParseDecimal64(testvals.val2)
dec64vals.expected, expectedErr = ParseDecimal64(testvals.expectedResult)

if err1 != nil || err2 != nil || expectedErr != nil {
dec64vals.parseError = fmt.Errorf("\nerror parsing in test: %s: \n val 1:%s: \n val 2: %s\n expected: %s ",
testvals.testName,
err1,
err2,
expectedErr)
}
return
}

// runTest completes the tests and returns a boolean and string on if the test passes.
func runTest(testVals decValContainer, testValStrings testCaseStrings) error {
calcRestul := execOp(testVals.val1, testVals.val2, testValStrings.testFunc)
flavor1, _, _, _ := calcRestul.parts()
flavor2, _, _, _ := testVals.expected.parts()
if flavor1 == flSNaN || flavor2 == flSNaN {
if testVals.expected.Cmp(calcRestul) == -2 {
return nil
}

joshcarp marked this conversation as resolved.
Show resolved Hide resolved
return fmt.Errorf(
"\nfailed NaN %s \n %v %s %v == %v \n expected result: %v ",
testValStrings.testName,
testValStrings.val1,
testValStrings.testFunc,
testValStrings.val2,
calcRestul,
testVals.expected)

} else if testVals.expected.Cmp(calcRestul) != 0 {
return fmt.Errorf(
"\nfailed %s \n %v %s %v == %v \n expected result: %v ",
testValStrings.testName,
testValStrings.val1,
testValStrings.testFunc,
testValStrings.val2,
calcRestul,
testVals.expected)
}
return nil
}

joshcarp marked this conversation as resolved.
Show resolved Hide resolved
// TODO: get runTest to run more functions such as FMA.
// execOp returns the calculated answer to the operation as Decimal64.
func execOp(val1, val2 Decimal64, op string) Decimal64 {
switch op {
case "add":
return val1.Add(val2)
case "multiply":
return val1.Mul(val2)
case "abs":
return val1.Abs()
case "divide":
return val1.Quo(val2)
default:
panic("end of operation function no tests ran")
}
}
1 change: 1 addition & 0 deletions dectest/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.decTest linguist-vendored
160 changes: 160 additions & 0 deletions dectest/abs.decTest
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
------------------------------------------------------------------------
joshcarp marked this conversation as resolved.
Show resolved Hide resolved
-- abs.decTest -- decimal absolute value --
-- Copyright (c) Mike Cowlishaw, 1981, 2010. All rights reserved. --
-- Parts copyright (c) IBM Corporation, 1981, 2008. --
------------------------------------------------------------------------
-- Please see the document "General Decimal Arithmetic Testcases" --
-- at http://speleotrove.com/decimal for the description of --
-- these testcases. --
-- --
-- These testcases are experimental ('beta' versions), and they --
-- may contain errors. They are offered on an as-is basis. In --
-- particular, achieving the same results as the tests here is not --
-- a guarantee that an implementation complies with any Standard --
-- or specification. The tests are not exhaustive. --
-- --
-- Please send comments, suggestions, and corrections to the author: --
-- Mike Cowlishaw, [email protected] --
------------------------------------------------------------------------
version: 2.62

-- This set of tests primarily tests the existence of the operator.
-- Additon, subtraction, rounding, and more overflows are tested
-- elsewhere.

precision: 9
rounding: half_up
maxExponent: 384
minexponent: -383
extended: 1

absx001 abs '1' -> '1'
absx002 abs '-1' -> '1'
absx003 abs '1.00' -> '1.00'
absx004 abs '-1.00' -> '1.00'
absx005 abs '0' -> '0'
absx006 abs '0.00' -> '0.00'
absx007 abs '00.0' -> '0.0'
absx008 abs '00.00' -> '0.00'
absx009 abs '00' -> '0'

absx010 abs '-2' -> '2'
absx011 abs '2' -> '2'
absx012 abs '-2.00' -> '2.00'
absx013 abs '2.00' -> '2.00'
absx014 abs '-0' -> '0'
absx015 abs '-0.00' -> '0.00'
absx016 abs '-00.0' -> '0.0'
absx017 abs '-00.00' -> '0.00'
absx018 abs '-00' -> '0'

absx020 abs '-2000000' -> '2000000'
absx021 abs '2000000' -> '2000000'
precision: 7
absx022 abs '-2000000' -> '2000000'
absx023 abs '2000000' -> '2000000'
precision: 6
absx024 abs '-2000000' -> '2.00000E+6' Rounded
absx025 abs '2000000' -> '2.00000E+6' Rounded
precision: 3
absx026 abs '-2000000' -> '2.00E+6' Rounded
absx027 abs '2000000' -> '2.00E+6' Rounded

absx030 abs '+0.1' -> '0.1'
absx031 abs '-0.1' -> '0.1'
absx032 abs '+0.01' -> '0.01'
absx033 abs '-0.01' -> '0.01'
absx034 abs '+0.001' -> '0.001'
absx035 abs '-0.001' -> '0.001'
absx036 abs '+0.000001' -> '0.000001'
absx037 abs '-0.000001' -> '0.000001'
absx038 abs '+0.000000000001' -> '1E-12'
absx039 abs '-0.000000000001' -> '1E-12'

-- examples from decArith
precision: 9
absx040 abs '2.1' -> '2.1'
absx041 abs '-100' -> '100'
absx042 abs '101.5' -> '101.5'
absx043 abs '-101.5' -> '101.5'

-- more fixed, potential LHS swaps/overlays if done by subtract 0
precision: 9
absx060 abs '-56267E-10' -> '0.0000056267'
absx061 abs '-56267E-5' -> '0.56267'
absx062 abs '-56267E-2' -> '562.67'
absx063 abs '-56267E-1' -> '5626.7'
absx065 abs '-56267E-0' -> '56267'

-- overflow tests
maxexponent: 999999999
minexponent: -999999999
precision: 3
absx120 abs 9.999E+999999999 -> Infinity Inexact Overflow Rounded

-- subnormals and underflow
precision: 3
maxexponent: 999
minexponent: -999
absx210 abs 1.00E-999 -> 1.00E-999
absx211 abs 0.1E-999 -> 1E-1000 Subnormal
absx212 abs 0.10E-999 -> 1.0E-1000 Subnormal
absx213 abs 0.100E-999 -> 1.0E-1000 Subnormal Rounded
absx214 abs 0.01E-999 -> 1E-1001 Subnormal
-- next is rounded to Emin
absx215 abs 0.999E-999 -> 1.00E-999 Inexact Rounded Subnormal Underflow
absx216 abs 0.099E-999 -> 1.0E-1000 Inexact Rounded Subnormal Underflow
absx217 abs 0.009E-999 -> 1E-1001 Inexact Rounded Subnormal Underflow
absx218 abs 0.001E-999 -> 0E-1001 Inexact Rounded Subnormal Underflow Clamped
absx219 abs 0.0009E-999 -> 0E-1001 Inexact Rounded Subnormal Underflow Clamped
absx220 abs 0.0001E-999 -> 0E-1001 Inexact Rounded Subnormal Underflow Clamped

absx230 abs -1.00E-999 -> 1.00E-999
absx231 abs -0.1E-999 -> 1E-1000 Subnormal
absx232 abs -0.10E-999 -> 1.0E-1000 Subnormal
absx233 abs -0.100E-999 -> 1.0E-1000 Subnormal Rounded
absx234 abs -0.01E-999 -> 1E-1001 Subnormal
-- next is rounded to Emin
absx235 abs -0.999E-999 -> 1.00E-999 Inexact Rounded Subnormal Underflow
absx236 abs -0.099E-999 -> 1.0E-1000 Inexact Rounded Subnormal Underflow
absx237 abs -0.009E-999 -> 1E-1001 Inexact Rounded Subnormal Underflow
absx238 abs -0.001E-999 -> 0E-1001 Inexact Rounded Subnormal Underflow Clamped
absx239 abs -0.0009E-999 -> 0E-1001 Inexact Rounded Subnormal Underflow Clamped
absx240 abs -0.0001E-999 -> 0E-1001 Inexact Rounded Subnormal Underflow Clamped

-- long operand tests
maxexponent: 999
minexponent: -999
precision: 9
absx301 abs 12345678000 -> 1.23456780E+10 Rounded
absx302 abs 1234567800 -> 1.23456780E+9 Rounded
absx303 abs 1234567890 -> 1.23456789E+9 Rounded
absx304 abs 1234567891 -> 1.23456789E+9 Inexact Rounded
absx305 abs 12345678901 -> 1.23456789E+10 Inexact Rounded
absx306 abs 1234567896 -> 1.23456790E+9 Inexact Rounded

precision: 15
absx321 abs 12345678000 -> 12345678000
absx322 abs 1234567800 -> 1234567800
absx323 abs 1234567890 -> 1234567890
absx324 abs 1234567891 -> 1234567891
absx325 abs 12345678901 -> 12345678901
absx326 abs 1234567896 -> 1234567896


-- Specials
precision: 9

-- specials
absx520 abs 'Inf' -> 'Infinity'
absx521 abs '-Inf' -> 'Infinity'
absx522 abs NaN -> NaN
absx523 abs sNaN -> NaN Invalid_operation
absx524 abs NaN22 -> NaN22
absx525 abs sNaN33 -> NaN33 Invalid_operation
absx526 abs -NaN22 -> -NaN22
absx527 abs -sNaN33 -> -NaN33 Invalid_operation

-- Null tests
absx900 abs # -> NaN Invalid_operation

Loading