blob: c4f802a6f6bc225b0143af968bd545681d205eb1 [file] [log] [blame]
xinau41e30c62019-09-06 11:05:02 +00001// Copyright 2018 The CUE Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package list
16
17import (
18 "fmt"
19
xinau41e30c62019-09-06 11:05:02 +000020 "github.com/cockroachdb/apd/v2"
Koichi Shiraishi30a4bee2019-12-26 03:06:48 +090021
22 "cuelang.org/go/internal"
xinau41e30c62019-09-06 11:05:02 +000023)
24
25// Avg returns the average value of a non empty list xs.
26func Avg(xs []*internal.Decimal) (*internal.Decimal, error) {
27 if 0 == len(xs) {
28 return nil, fmt.Errorf("empty list")
29 }
30
31 s := apd.New(0, 0)
32 for _, x := range xs {
33 _, err := internal.BaseContext.Add(s, x, s)
34 if err != nil {
35 return nil, err
36 }
37 }
38
39 var d apd.Decimal
40 l := apd.New(int64(len(xs)), 0)
41 _, err := internal.BaseContext.Quo(&d, s, l)
42 if err != nil {
43 return nil, err
44 }
45 return &d, nil
46}
47
48// Max returns the maximum value of a non empty list xs.
49func Max(xs []*internal.Decimal) (*internal.Decimal, error) {
50 if 0 == len(xs) {
51 return nil, fmt.Errorf("empty list")
52 }
53
54 max := xs[0]
55 for _, x := range xs[1:] {
56 if -1 == max.Cmp(x) {
57 max = x
58 }
59 }
60 return max, nil
61}
62
63// Min returns the minimum value of a non empty list xs.
64func Min(xs []*internal.Decimal) (*internal.Decimal, error) {
65 if 0 == len(xs) {
66 return nil, fmt.Errorf("empty list")
67 }
68
69 min := xs[0]
70 for _, x := range xs[1:] {
71 if +1 == min.Cmp(x) {
72 min = x
73 }
74 }
75 return min, nil
76}
77
78// Product returns the product of a non empty list xs.
79func Product(xs []*internal.Decimal) (*internal.Decimal, error) {
80 d := apd.New(1, 0)
81 for _, x := range xs {
82 _, err := internal.BaseContext.Mul(d, x, d)
83 if err != nil {
84 return nil, err
85 }
86 }
87 return d, nil
88}
89
xinau5ac1fbf2019-10-04 14:05:30 +000090// Range generates a list of numbers using a start value, a limit value, and a
91// step value.
92//
93// For instance:
94//
95// Range(0, 5, 2)
96//
97// results in
98//
99// [0, 2, 4]
100//
101func Range(start, limit, step *internal.Decimal) ([]*internal.Decimal, error) {
102 if step.IsZero() {
103 return nil, fmt.Errorf("step must be non zero")
104 }
105
106 if !step.Negative && +1 == start.Cmp(limit) {
107 return nil, fmt.Errorf("end must be greater than start when step is positive")
108 }
109
110 if step.Negative && -1 == start.Cmp(limit) {
111 return nil, fmt.Errorf("end must be less than start when step is negative")
112 }
113
114 var vals []*internal.Decimal
115 num := start
116 for {
117 if !step.Negative && -1 != num.Cmp(limit) {
118 break
119 }
120
121 if step.Negative && +1 != num.Cmp(limit) {
122 break
123 }
124
125 vals = append(vals, num)
126 d := apd.New(0, 0)
127 _, err := internal.BaseContext.Add(d, step, num)
128 if err != nil {
129 return nil, err
130 }
131 num = d
132 }
133 return vals, nil
134}
135
xinau41e30c62019-09-06 11:05:02 +0000136// Sum returns the sum of a list non empty xs.
137func Sum(xs []*internal.Decimal) (*internal.Decimal, error) {
138 d := apd.New(0, 0)
139 for _, x := range xs {
140 _, err := internal.BaseContext.Add(d, x, d)
141 if err != nil {
142 return nil, err
143 }
144 }
145 return d, nil
146}