gitee.com/quant1x/num@v0.3.2/arithmetics.go (about)

     1  package num
     2  
     3  // 四则运算 (arithmetics)
     4  
     5  // UnaryOperations 一元运算 unary operations
     6  func UnaryOperations[T Number](x []T, f32 func([]float32) []float32, f64 func([]float64) []float64, cany func([]T) []T) []T {
     7  	var t []T
     8  	if len(x) == 0 {
     9  		return t
    10  	}
    11  	var d any
    12  	var s any
    13  	s = x
    14  	switch fs := s.(type) {
    15  	case []float32:
    16  		d = f32(fs)
    17  	case []float64:
    18  		d = f64(fs)
    19  	default:
    20  		d = cany(x)
    21  	}
    22  	return d.([]T)
    23  }
    24  
    25  func UnaryOperations1[T Number](x []T, f32 func([]float32) float32, f64 func([]float64) float64, cany func([]T) T) T {
    26  	var t T
    27  	if len(x) == 0 {
    28  		return t
    29  	}
    30  	var d any
    31  	var s any
    32  	s = x
    33  	switch fs := s.(type) {
    34  	case []float32:
    35  		d = f32(fs)
    36  	case []float64:
    37  		d = f64(fs)
    38  	default:
    39  		d = cany(x)
    40  	}
    41  	return d.(T)
    42  }
    43  
    44  // UnaryOperations2 一元运算 unary operations
    45  //
    46  //	运算和返回值是两种类型
    47  func UnaryOperations2[T Number, E Number](x []T, f32 func([]float32) E, f64 func([]float64) E, cany func([]T) E) E {
    48  	if len(x) == 0 {
    49  		return E(0)
    50  	}
    51  	var d any
    52  	var s any
    53  	s = x
    54  	switch fs := s.(type) {
    55  	case []float32:
    56  		d = f32(fs)
    57  	case []float64:
    58  		d = f64(fs)
    59  	default:
    60  		d = cany(x)
    61  	}
    62  	return d.(E)
    63  }
    64  
    65  // BinaryOperations 二元运算 binary operations
    66  //
    67  //	Binary operation
    68  //	calculate
    69  func BinaryOperations[T Number](x []T, y any, f32 func(x, y []float32) []float32, f64 func(x, y []float64) []float64, cany func(x, y []T) []T) []T {
    70  	var d any
    71  	length := len(x)
    72  	var s any = x
    73  	switch vs := s.(type) {
    74  	case []float32:
    75  		f32s := AnyToSlice[float32](y, length)
    76  		//vs = FillNa(vs, 0.00)
    77  		//f32s = FillNa(f32s, 0.00)
    78  		d = f32(vs, f32s)
    79  	case []float64:
    80  		f64s := AnyToSlice[float64](y, length)
    81  		//vs = FillNa(vs, 0.00)
    82  		//f64s = FillNa(f64s, 0.00)
    83  		d = f64(vs, f64s)
    84  	default:
    85  		ys := AnyToSlice[T](y, length)
    86  		d = cany(x, ys)
    87  	}
    88  	return d.([]T)
    89  }
    90  
    91  func BinaryOperations2[T BaseType, E BaseType](x, y []T, f32 func(x, y []float32) []E, f64 func(x, y []float64) []E, cany func(x, y []T) []E) []E {
    92  	var d any
    93  	length := len(x)
    94  	var s any = x
    95  	switch vs := s.(type) {
    96  	case []float32:
    97  		f32s := AnyToSlice[float32](y, length)
    98  		d = f32(vs, f32s)
    99  	case []float64:
   100  		f64s := AnyToSlice[float64](y, length)
   101  		d = f64(vs, f64s)
   102  	default:
   103  		ys := AnyToSlice[T](y, length)
   104  		d = cany(x, ys)
   105  	}
   106  	return d.([]E)
   107  }
   108  
   109  // 三元运算 triple operations
   110  /*
   111  const (
   112  	__k_calc_add = 1 // 加
   113  	__k_calc_sub = 2 // 减
   114  	__k_calc_mul = 3 // 乘
   115  	__k_calc_div = 4 // 除
   116  	__k_calc_mod = 5 // 取模
   117  )
   118  
   119  var (
   120  	// 加
   121  	__calc_add = func(f1, f2 DType) DType {
   122  		return f1 + f2
   123  	}
   124  	// 减
   125  	__calc_sub = func(f1, f2 DType) DType {
   126  		return f1 - f2
   127  	}
   128  	// 乘
   129  	__calc_mul = func(f1, f2 DType) DType {
   130  		return f1 * f2
   131  	}
   132  	// 除
   133  	__calc_div = func(f1, f2 DType) DType {
   134  		return f1 / f2
   135  	}
   136  	// 取模
   137  	__calc_mod = func(f1, f2 DType) DType {
   138  		return math.Mod(f1, f2)
   139  	}
   140  )
   141  
   142  // 重构
   143  
   144  func __arithmetic[T ~[]E, E Number](x T, y any, c int, calculator func(f1, f2 DType) E) []E {
   145  	if __y, ok := y.(Series); ok {
   146  		y = __y.Values()
   147  	}
   148  	var d = []E{}
   149  	switch Y := y.(type) {
   150  	case nil, int8, uint8, int16, uint16, int32, uint32, int64, uint64, int, uint, float32, float64, bool, string:
   151  		f2 := Any2DType(Y)
   152  		d = __arithmetic_dtype(x, f2, c, calculator)
   153  	case []float32:
   154  		d = __arithmetic_slice(x, Y, c, calculator)
   155  	case []float64:
   156  		d = __arithmetic_slice(x, Y, c, calculator)
   157  	case []int:
   158  		d = __arithmetic_slice(x, Y, c, calculator)
   159  	case []int8:
   160  		d = __arithmetic_slice(x, Y, c, calculator)
   161  	case []int16:
   162  		d = __arithmetic_slice(x, Y, c, calculator)
   163  	case []int32:
   164  		d = __arithmetic_slice(x, Y, c, calculator)
   165  	case []int64:
   166  		d = __arithmetic_slice(x, Y, c, calculator)
   167  	case []uint:
   168  		d = __arithmetic_slice(x, Y, c, calculator)
   169  	case []uint8:
   170  		d = __arithmetic_slice(x, Y, c, calculator)
   171  	case []uint16:
   172  		d = __arithmetic_slice(x, Y, c, calculator)
   173  	case []uint32:
   174  		d = __arithmetic_slice(x, Y, c, calculator)
   175  	case []uint64:
   176  		d = __arithmetic_slice(x, Y, c, calculator)
   177  	case []uintptr:
   178  		d = __arithmetic_slice(x, Y, c, calculator)
   179  	//case []string:
   180  	//	d = __arithmetic_slice(x, Y, c, calculator)
   181  	//case []bool:
   182  	//	d = __arithmetic_slice(x, Y, c, calculator)
   183  	default:
   184  		// 其它未知类型抛异常
   185  		panic(TypeError(y))
   186  	}
   187  	return d
   188  }
   189  
   190  // 切片和dtype对比, 不用考虑slice长度对齐的问题
   191  func __arithmetic_dtype[T ~[]E, E Number](x T, y DType, c int, calculator func(f1, f2 DType) E) []E {
   192  	var d any
   193  	xLen := len(x)
   194  	kind := checkoutRawType(x)
   195  	switch {
   196  	case kind == reflect.Float64 && c == __k_calc_add:
   197  		fs := make([]float64, xLen)
   198  		d = num.AddNumber_Into(fs, any(x).([]float64), y)
   199  	case kind == reflect.Float64 && c == __k_calc_sub:
   200  		fs := make([]float64, xLen)
   201  		d = num.SubNumber_Into(fs, any(x).([]float64), y)
   202  	case kind == reflect.Float64 && c == __k_calc_mul:
   203  		fs := make([]float64, xLen)
   204  		d = num.MulNumber_Into(fs, any(x).([]float64), y)
   205  	case kind == reflect.Float64 && c == __k_calc_div:
   206  		fs := make([]float64, xLen)
   207  		d = num.DivNumber_Into(fs, any(x).([]float64), y)
   208  	case kind == reflect.Float32 && c == __k_calc_add:
   209  		fs := make([]float32, xLen)
   210  		d = num32.AddNumber_Into(fs, any(x).([]float32), float32(y))
   211  	case kind == reflect.Float32 && c == __k_calc_sub:
   212  		fs := make([]float32, xLen)
   213  		d = num32.SubNumber_Into(fs, any(x).([]float32), float32(y))
   214  	case kind == reflect.Float32 && c == __k_calc_mul:
   215  		fs := make([]float32, xLen)
   216  		d = num32.MulNumber_Into(fs, any(x).([]float32), float32(y))
   217  	case kind == reflect.Float32 && c == __k_calc_div:
   218  		fs := make([]float32, xLen)
   219  		d = num32.DivNumber_Into(fs, any(x).([]float32), float32(y))
   220  	default:
   221  		b := y
   222  		bs := make([]E, xLen)
   223  		for i := 0; i < xLen; i++ {
   224  			a := Any2DType(x[i])
   225  			bs[i] = calculator(a, b)
   226  		}
   227  	}
   228  	return d.([]E)
   229  }
   230  
   231  // 切片和切片对比
   232  func __arithmetic_slice[T ~[]E, E Number, T2 ~[]E2, E2 Number](x T, y T2, c int, calculator func(f1, f2 DType) E) []E {
   233  	var d any
   234  	xLen := len(x)
   235  	yLen := len(y)
   236  
   237  	if xLen >= yLen {
   238  		es := make([]E, xLen)
   239  		switch xs := any(x).(type) {
   240  		case []float64:
   241  			num.Add_Into(es[:yLen], xs[:yLen], any(y).([]float64)[:yLen])
   242  		}
   243  		switch {
   244  		case xKind == reflect.Float64 && xKind == yKind && c == __k_calc_add:
   245  			num.Add_Into(es[:yLen], any(x).([]float64)[:yLen], any(y).([]float64)[:yLen])
   246  		case xKind == reflect.Float64 && xKind == yKind && c == __k_calc_sub:
   247  			num.Sub_Into(es[:yLen], any(x).([]float64)[:yLen], any(y).([]float64)[:yLen])
   248  		case xKind == reflect.Float64 && xKind == yKind && c == __k_calc_mul:
   249  			num.Mul_Into(es[:yLen], any(x).([]float64)[:yLen], any(y).([]float64)[:yLen])
   250  		case xKind == reflect.Float64 && xKind == yKind && c == __k_calc_div:
   251  			num.Div_Into(es[:yLen], any(x).([]float64)[:yLen], any(y).([]float64)[:yLen])
   252  		case xKind == reflect.Float32 && xKind == yKind && c == __k_calc_add:
   253  			num.Add_Into(es[:yLen], any(x).([]float64)[:yLen], any(y).([]float64)[:yLen])
   254  		case xKind == reflect.Float32 && xKind == yKind && c == __k_calc_sub:
   255  			num.Sub_Into(es[:yLen], any(x).([]float64)[:yLen], any(y).([]float64)[:yLen])
   256  		case xKind == reflect.Float32 && xKind == yKind && c == __k_calc_mul:
   257  			num.Mul_Into(es[:yLen], any(x).([]float64)[:yLen], any(y).([]float64)[:yLen])
   258  		case xKind == reflect.Float32 && xKind == yKind && c == __k_calc_div:
   259  			num.Div_Into(es[:yLen], any(x).([]float64)[:yLen], any(y).([]float64)[:yLen])
   260  		}
   261  		if xKind == reflect.Float64 && xKind == yKind && c == __k_calc_add {
   262  			num.Gt_Into(es[:yLen], any(x).([]float64)[:yLen], any(y).([]float64)[:yLen])
   263  		} else if xKind == reflect.Float64 && xKind == yKind && c == __k_compare_gte {
   264  			es := make([]float64, xLen)
   265  			num.Gte_Into(es[:yLen], any(x).([]float64)[:yLen], any(y).([]float64)[:yLen])
   266  		} else if xKind == reflect.Float64 && xKind == yKind && c == __k_compare_lt {
   267  			es := make([]float64, xLen)
   268  			num.Lt_Into(es[:yLen], any(x).([]float64)[:yLen], any(y).([]float64)[:yLen])
   269  		} else if xKind == reflect.Float64 && xKind == yKind && c == __k_compare_lte {
   270  			es := make([]float64, xLen)
   271  			num.Lte_Into(es[:yLen], any(x).([]float64)[:yLen], any(y).([]float64)[:yLen])
   272  		} else if xKind == reflect.Float32 && xKind == yKind && c == __k_compare_gt {
   273  			num32.Gt_Into(es[:yLen], any(x).([]float32)[:yLen], any(y).([]float32)[:yLen])
   274  		} else if xKind == reflect.Float32 && xKind == yKind && c == __k_compare_gte {
   275  			num32.Gte_Into(es[:yLen], any(x).([]float32)[:yLen], any(y).([]float32)[:yLen])
   276  		} else if xKind == reflect.Float32 && xKind == yKind && c == __k_compare_lt {
   277  			num32.Lt_Into(es[:yLen], any(x).([]float32)[:yLen], any(y).([]float32)[:yLen])
   278  		} else if xKind == reflect.Float32 && xKind == yKind && c == __k_compare_lte {
   279  			num32.Lte_Into(es[:yLen], any(x).([]float32)[:yLen], any(y).([]float32)[:yLen])
   280  		} else if xKind == reflect.Bool && xKind == yKind && c == __k_compare_and {
   281  			num.And_Into(es[:yLen], any(x).([]bool)[:yLen], any(y).([]bool)[:yLen])
   282  		} else {
   283  			for i := 0; i < yLen; i++ {
   284  				f1 := Any2DType(x[i])
   285  				f2 := Any2DType(y[i])
   286  				es[i] = calculator(f1, f2)
   287  			}
   288  		}
   289  		for i := yLen; i < xLen; i++ {
   290  			f1 := Any2DType(x[i])
   291  			f2 := DType(0)
   292  			es[i] = calculator(f1, f2)
   293  		}
   294  	} else {
   295  		es = make([]bool, yLen)
   296  		if xKind == reflect.Float64 && xKind == yKind && c == __k_compare_gt {
   297  			num.Gt_Into(es[:xLen], any(x).([]float64)[:xLen], any(y).([]float64)[:xLen])
   298  		} else if xKind == reflect.Float64 && xKind == yKind && c == __k_compare_gte {
   299  			num.Gte_Into(es[:xLen], any(x).([]float64)[:xLen], any(y).([]float64)[:xLen])
   300  		} else if xKind == reflect.Float64 && xKind == yKind && c == __k_compare_lt {
   301  			num.Lt_Into(es[:xLen], any(x).([]float64)[:xLen], any(y).([]float64)[:xLen])
   302  		} else if xKind == reflect.Float64 && xKind == yKind && c == __k_compare_lte {
   303  			num.Lte_Into(es[:xLen], any(x).([]float64)[:xLen], any(y).([]float64)[:xLen])
   304  		} else if xKind == reflect.Float32 && xKind == yKind && c == __k_compare_gt {
   305  			num32.Gt_Into(es[:xLen], any(x).([]float32)[:xLen], any(y).([]float32)[:xLen])
   306  		} else if xKind == reflect.Float32 && xKind == yKind && c == __k_compare_gte {
   307  			num32.Gte_Into(es[:xLen], any(x).([]float32)[:xLen], any(y).([]float32)[:xLen])
   308  		} else if xKind == reflect.Float32 && xKind == yKind && c == __k_compare_lt {
   309  			num32.Lt_Into(es[:xLen], any(x).([]float32)[:xLen], any(y).([]float32)[:xLen])
   310  		} else if xKind == reflect.Float32 && xKind == yKind && c == __k_compare_lte {
   311  			num32.Lte_Into(es[:xLen], any(x).([]float32)[:xLen], any(y).([]float32)[:xLen])
   312  		} else if xKind == reflect.Bool && xKind == yKind && c == __k_compare_and {
   313  			num.And_Into(es[:xLen], any(x).([]bool)[:xLen], any(y).([]bool)[:xLen])
   314  		} else {
   315  			for i := 0; i < xLen; i++ {
   316  				f1 := Any2DType(x[i])
   317  				f2 := Any2DType(y[i])
   318  				es[i] = calculator(f1, f2)
   319  			}
   320  		}
   321  		for i := xLen; i < yLen; i++ {
   322  			f1 := DType(0)
   323  			f2 := Any2DType(y[i])
   324  			es[i] = calculator(f1, f2)
   325  		}
   326  	}
   327  	return d.([]E)
   328  }
   329  */