This is an automated email from the ASF dual-hosted git repository.

zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/main by this push:
     new 8c9143436a GH-35162: [Go] Float16 arithmetic (#35163)
8c9143436a is described below

commit 8c9143436a73145cbe03648ed694c490e5d9e75d
Author: Igor Izvekov <[email protected]>
AuthorDate: Mon Apr 17 17:35:24 2023 +0300

    GH-35162: [Go] Float16 arithmetic (#35163)
    
    
    
    ### Rationale for this change
    
    ### What changes are included in this PR?
    
    ### Are these changes tested?
    Yes
    
    ### Are there any user-facing changes?
    Yes
    * Closes: #35162
    
    Authored-by: izveigor <[email protected]>
    Signed-off-by: Matt Topol <[email protected]>
---
 go/arrow/float16/float16.go      |  95 ++++++++++++++++++
 go/arrow/float16/float16_test.go | 205 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 300 insertions(+)

diff --git a/go/arrow/float16/float16.go b/go/arrow/float16/float16.go
index c46a3a1a00..4e03d13df0 100644
--- a/go/arrow/float16/float16.go
+++ b/go/arrow/float16/float16.go
@@ -66,5 +66,100 @@ func (f Num) Float32() float32 {
        return math.Float32frombits((sn << 31) | (res << 23) | (fc << 13))
 }
 
+func (n Num) Negate() Num {
+       return Num{bits: n.bits ^ 0x8000}
+}
+
+func (n Num) Add(rhs Num) Num {
+       return New(n.Float32() + rhs.Float32())
+}
+
+func (n Num) Sub(rhs Num) Num {
+       return New(n.Float32() - rhs.Float32())
+}
+
+func (n Num) Mul(rhs Num) Num {
+       return New(n.Float32() * rhs.Float32())
+}
+
+func (n Num) Div(rhs Num) Num {
+       return New(n.Float32() / rhs.Float32())
+}
+
+// Greater returns true if the value represented by n is > other
+func (n Num) Greater(other Num) bool {
+       return n.Float32() > other.Float32()
+}
+
+// GreaterEqual returns true if the value represented by n is >= other
+func (n Num) GreaterEqual(other Num) bool {
+       return n.Float32() >= other.Float32()
+}
+
+// Less returns true if the value represented by n is < other
+func (n Num) Less(other Num) bool {
+       return n.Float32() < other.Float32()
+}
+
+// LessEqual returns true if the value represented by n is <= other
+func (n Num) LessEqual(other Num) bool {
+       return n.Float32() <= other.Float32()
+}
+
+// Max returns the largest Decimal128 that was passed in the arguments
+func Max(first Num, rest ...Num) Num {
+       answer := first
+       for _, number := range rest {
+               if number.Greater(answer) {
+                       answer = number
+               }
+       }
+       return answer
+}
+
+// Min returns the smallest Decimal128 that was passed in the arguments
+func Min(first Num, rest ...Num) Num {
+       answer := first
+       for _, number := range rest {
+               if number.Less(answer) {
+                       answer = number
+               }
+       }
+       return answer
+}
+
+// Cmp compares the numbers represented by n and other and returns:
+//
+//     +1 if n > other
+//      0 if n == other
+//     -1 if n < other
+func (n Num) Cmp(other Num) int {
+       switch {
+       case n.Greater(other):
+               return 1
+       case n.Less(other):
+               return -1
+       }
+       return 0
+}
+
+func (n Num) Abs() Num {
+       switch n.Sign() {
+       case -1:
+               return n.Negate()
+       }
+       return n
+}
+
+func (n Num) Sign() int {
+       f := n.Float32()
+       if f > 0 {
+               return 1
+       } else if f == 0 {
+               return 0
+       }
+       return -1
+}
+
 func (f Num) Uint16() uint16 { return f.bits }
 func (f Num) String() string { return 
strconv.FormatFloat(float64(f.Float32()), 'g', -1, 32) }
diff --git a/go/arrow/float16/float16_test.go b/go/arrow/float16/float16_test.go
index aa96a2f6fc..5294e1798d 100644
--- a/go/arrow/float16/float16_test.go
+++ b/go/arrow/float16/float16_test.go
@@ -43,3 +43,208 @@ func TestFloat16(t *testing.T) {
                assert.Equal(t, k.String(), fmt.Sprintf("%v", v), "string 
representation differ")
        }
 }
+
+func TestAdd(t *testing.T) {
+       for _, tc := range []struct {
+               n    Num
+               rhs  Num
+               want Num
+       }{
+               {Num{bits: 0x0000}, Num{bits: 0x0000}, Num{bits: 0x0000}}, // 0 
+ 0 = 0
+               {Num{bits: 0x3c00}, Num{bits: 0x4000}, Num{bits: 0x4200}}, // 1 
+ 2 = 3
+               {Num{bits: 0x4248}, Num{bits: 0x3245}, Num{bits: 0x42AC}}, // 
3.141 + 0.196 = 3.336
+       } {
+               t.Run("add", func(t *testing.T) {
+                       n := tc.n.Add(tc.rhs)
+                       if got, want := n, tc.want; got != want {
+                               t.Fatalf("invalid value. got=%v, want=%v", got, 
want)
+                       }
+               })
+       }
+}
+
+func TestSub(t *testing.T) {
+       for _, tc := range []struct {
+               n    Num
+               rhs  Num
+               want Num
+       }{
+               {Num{bits: 0x0000}, Num{bits: 0x0000}, Num{bits: 0x0000}}, // 0 
- 0 = 0
+               {Num{bits: 0x3c00}, Num{bits: 0x4000}, Num{bits: 0xBC00}}, // 1 
- 2 = -1
+               {Num{bits: 0x4248}, Num{bits: 0x3245}, Num{bits: 0x41E3}}, // 
3.141 - 0.196 = 2.944
+       } {
+               t.Run("sub", func(t *testing.T) {
+                       n := tc.n.Sub(tc.rhs)
+                       if got, want := n, tc.want; got != want {
+                               t.Fatalf("invalid value. got=%v, want=%v", got, 
want)
+                       }
+               })
+       }
+}
+
+func TestMul(t *testing.T) {
+       for _, tc := range []struct {
+               n    Num
+               rhs  Num
+               want Num
+       }{
+               {Num{bits: 0x0000}, Num{bits: 0x0000}, Num{bits: 0x0000}}, // 0 
* 0 = 0
+               {Num{bits: 0x3c00}, Num{bits: 0x4000}, Num{bits: 0x4000}}, // 1 
* 2 = 2
+               {Num{bits: 0x4248}, Num{bits: 0x3245}, Num{bits: 0x38EC}}, // 
3.141 * 0.196 = 0.6153
+       } {
+               t.Run("mul", func(t *testing.T) {
+                       n := tc.n.Mul(tc.rhs)
+                       if got, want := n, tc.want; got != want {
+                               t.Fatalf("invalid value. got=%v, want=%v", got, 
want)
+                       }
+               })
+       }
+}
+
+func TestDiv(t *testing.T) {
+       for _, tc := range []struct {
+               n    Num
+               rhs  Num
+               want Num
+       }{
+               {Num{bits: 0x0000}, Num{bits: 0x3c00}, Num{bits: 0x0000}}, // 0 
/ 1 = 0
+               {Num{bits: 0x3c00}, Num{bits: 0x4000}, Num{bits: 0x3800}}, // 1 
/ 2 = 0.5
+               {Num{bits: 0x4248}, Num{bits: 0x3245}, Num{bits: 0x4C01}}, // 
3.141 * 0.196 = 16.02
+       } {
+               t.Run("div", func(t *testing.T) {
+                       n := tc.n.Div(tc.rhs)
+                       if got, want := n, tc.want; got != want {
+                               t.Fatalf("invalid value. got=%v, want=%v", got, 
want)
+                       }
+               })
+       }
+}
+
+func TestGreater(t *testing.T) {
+       for _, tc := range []struct {
+               n    Num
+               rhs  Num
+               want bool
+       }{
+               {Num{bits: 0x3c00}, Num{bits: 0x4000}, false}, // 1 > 2 = false
+               {Num{bits: 0x4900}, Num{bits: 0x4900}, false}, // 10 == 10 = 
false
+               {Num{bits: 0x4248}, Num{bits: 0x3245}, true},  // 3.141 > 0.196 
= true
+       } {
+               t.Run("greater", func(t *testing.T) {
+                       n := tc.n.Greater(tc.rhs)
+                       if got, want := n, tc.want; got != want {
+                               t.Fatalf("invalid value. got=%v, want=%v", got, 
want)
+                       }
+               })
+       }
+}
+
+func TestLess(t *testing.T) {
+       for _, tc := range []struct {
+               n    Num
+               rhs  Num
+               want bool
+       }{
+               {Num{bits: 0x3c00}, Num{bits: 0x4000}, true},  // 1 < 2 = true
+               {Num{bits: 0x4900}, Num{bits: 0x4900}, false}, // 10 == 10 = 
false
+               {Num{bits: 0x4248}, Num{bits: 0x3245}, false}, // 3.141 < 0.196 
= false
+       } {
+               t.Run("less", func(t *testing.T) {
+                       n := tc.n.Less(tc.rhs)
+                       if got, want := n, tc.want; got != want {
+                               t.Fatalf("invalid value. got=%v, want=%v", got, 
want)
+                       }
+               })
+       }
+}
+
+func TestCmp(t *testing.T) {
+       for _, tc := range []struct {
+               n    Num
+               rhs  Num
+               want int
+       }{
+               {Num{bits: 0x3c00}, Num{bits: 0x4000}, -1}, // cmp(1, 2) = -1
+               {Num{bits: 0x4900}, Num{bits: 0x4900}, 0}, // cmp(10, 10) = 0
+               {Num{bits: 0x4248}, Num{bits: 0x3245}, 1},  // cmp(3.141, 
0.196) = 1
+       } {
+               t.Run("cmp", func(t *testing.T) {
+                       n := tc.n.Cmp(tc.rhs)
+                       if got, want := n, tc.want; got != want {
+                               t.Fatalf("invalid value. got=%v, want=%v", got, 
want)
+                       }
+               })
+       }
+}
+
+func TestMax(t *testing.T) {
+       for _, tc := range []struct {
+               n    Num
+               rhs  []Num
+               want Num
+       }{
+               {Num{bits: 0x3c00}, []Num{{bits: 0x4000}, {bits: 0x4580}, 
{bits: 0x3C00}, {bits: 0x4247}}, Num{bits: 0x4580}}, // max(2, 5.5, 1, 3.14) = 
5.5
+               {Num{bits: 0x4248}, []Num{{bits: 0xC000}, {bits: 0xC580}, 
{bits: 0x3C00}, {bits: 0x4247}}, Num{bits: 0x4248}}, // max(-2, -5.5, 1, 3.14) 
= 3.14
+       } {
+               t.Run("max", func(t *testing.T) {
+                       n := Max(tc.n, tc.rhs...)
+                       if got, want := n, tc.want; got != want {
+                               t.Fatalf("invalid value. got=%v, want=%v", got, 
want)
+                       }
+               })
+       }
+}
+
+func TestMin(t *testing.T) {
+       for _, tc := range []struct {
+               n    Num
+               rhs  []Num
+               want Num
+       }{
+               {Num{bits: 0x3c00}, []Num{{bits: 0x4000}, {bits: 0x4580}, 
{bits: 0x3C00}, {bits: 0x4247}}, Num{bits: 0x3C00}}, // min(2, 5.5, 1, 3.14) = 1
+               {Num{bits: 0x4248}, []Num{{bits: 0x4000}, {bits: 0xC580}, 
{bits: 0xBC00}, {bits: 0x4247}}, Num{bits: 0xC580}}, // min(2, -5.5, -1, 3.14) 
= -5.5
+       } {
+               t.Run("min", func(t *testing.T) {
+                       n := Min(tc.n, tc.rhs...)
+                       if got, want := n, tc.want; got != want {
+                               t.Fatalf("invalid value. got=%v, want=%v", got, 
want)
+                       }
+               })
+       }
+}
+
+func TestAbs(t *testing.T) {
+       for _, tc := range []struct {
+               n    Num
+               want Num
+       }{
+               {Num{bits: 0x4580}, Num{bits: 0x4580}}, // 5.5
+               {Num{bits: 0x0000}, Num{bits: 0x0000}}, // 0
+               {Num{bits: 0xC580}, Num{bits: 0x4580}}, // -5.5
+       } {
+               t.Run("abs", func(t *testing.T) {
+                       n := tc.n.Abs()
+                       if got, want := n, tc.want; got != want {
+                               t.Fatalf("invalid value. got=%v, want=%v", got, 
want)
+                       }
+               })
+       }
+}
+
+func TestSign(t *testing.T) {
+       for _, tc := range []struct {
+               n    Num
+               want int
+       }{
+               {Num{bits: 0x4580}, 1},  // 5.5
+               {Num{bits: 0x0000}, 0},  // 0
+               {Num{bits: 0xC580}, -1}, // -5.5
+       } {
+               t.Run("sign", func(t *testing.T) {
+                       n := tc.n.Sign()
+                       if got, want := n, tc.want; got != want {
+                               t.Fatalf("invalid value. got=%v, want=%v", got, 
want)
+                       }
+               })
+       }
+}

Reply via email to