diff --git a/module/hisabati.go b/module/hisabati.go new file mode 100644 index 0000000..583905d --- /dev/null +++ b/module/hisabati.go @@ -0,0 +1,713 @@ +package module + +import ( + "math" + + "github.com/AvicennaJr/Nuru/object" +) + +var MathFunctions = map[string]object.ModuleFunction{ + "PI": pi, + "e": e, + "phi": phi, + "ln10": ln10, + "ln2": ln2, + "log10e": log10e, + "log2e": log2e, + "log2": log2, + "sqrt1_2": sqrt1_2, + "sqrt2": sqrt2, + "sqrt3": sqrt3, + "sqrt5": sqrt5, + "EPSILON": epsilon, + "abs": abs, + "sign": sign, + "ceil": ceil, + "floor": floor, + "sqrt": sqrt, + "cbrt": cbrt, + "root": root, + "hypot": hypot, + "factorial":factorial, + "round": round, + "max": max, + "min": min, + "exp": exp, + "expm1": expm1, + "log": log, + "log10": log10, + "log1p": log1p, + "cos": cos, + "sin": sin, + "tan": tan, + "acos": acos, + "asin": asin, + "atan": atan, + "cosh": cosh, + "sinh": sinh, + "tanh": tanh, + "acosh": acosh, + "asinh": asinh, + "atanh": atanh, + "atan2": atan2, +} + +var Constants = map[string]object.Object{ + "PI": &object.Float{Value: math.Pi}, + "e": &object.Float{Value: math.E}, + "phi": &object.Float{Value: (1 + math.Sqrt(5)) / 2}, + "ln10": &object.Float{Value: math.Log10E}, + "ln2": &object.Float{Value: math.Ln2}, + "log10e": &object.Float{Value: math.Log10E}, + "log2e": &object.Float{Value: math.Log2E}, + "sqrt1_2": &object.Float{Value: 1 / math.Sqrt2}, + "sqrt2": &object.Float{Value: math.Sqrt2}, + "sqrt3": &object.Float{Value: math.Sqrt(3)}, + "sqrt5": &object.Float{Value: math.Sqrt(5)}, + "EPSILON": &object.Float{Value: 2.220446049250313e-16}, +} + +func pi(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: math.Pi} +} + +func e(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: math.E} +} + +func phi(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: (1 + math.Sqrt(5)) / 2} +} + +func ln10(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: math.Log10E} +} + +func ln2(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: math.Ln2} +} + +func log10e(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: math.Log10E} +} + +func log2e(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: math.Log2E} +} + +func sqrt1_2(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: 1 / math.Sqrt2} +} + +func sqrt2(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: math.Sqrt2} +} + +func sqrt3(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: math.Sqrt(3)} +} + +func sqrt5(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: math.Sqrt(5)} +} + +func epsilon(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: 2.220446049250313e-16} +} + +func abs(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.INTEGER_OBJ && args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe namba"} + } + switch arg := args[0].(type) { + case *object.Integer: + if arg.Value < 0 { + return &object.Integer{Value: -arg.Value} + } + return arg + case *object.Float: + if arg.Value < 0 { + return &object.Float{Value: -arg.Value} + } + return arg + default: + return &object.Error{Message: "Hoja lazima iwe namba"} + } +} + +func sign(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + switch arg := args[0].(type) { + case *object.Integer: + if arg.Value == 0 { + return &object.Integer{Value: 0} + } else if arg.Value > 0 { + return &object.Integer{Value: 1} + } else { + return &object.Integer{Value: -1} + } + case *object.Float: + if arg.Value == 0 { + return &object.Integer{Value: 0} + } else if arg.Value > 0 { + return &object.Integer{Value: 1} + } else { + return &object.Integer{Value: -1} + } + default: + return &object.Error{Message: "Hoja lazima iwe namba"} + } +} + +func ceil(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.INTEGER_OBJ && args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe namba"} + } + switch arg := args[0].(type) { + case *object.Integer: + return &object.Integer{Value: arg.Value} + case *object.Float: + return &object.Integer{Value: int64(math.Ceil(arg.Value))} + default: + return &object.Error{Message: "Hoja lazima iwe namba"} + } +} + +func floor(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.INTEGER_OBJ && args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe namba"} + } + switch arg := args[0].(type) { + case *object.Integer: + return &object.Integer{Value: arg.Value} + case *object.Float: + return &object.Integer{Value: int64(math.Floor(arg.Value))} + default: + return &object.Error{Message: "Hoja lazima iwe namba"} + } +} + +func sqrt(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.INTEGER_OBJ && args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe namba"} + } + switch arg := args[0].(type) { + case *object.Integer: + return &object.Float{Value: math.Sqrt(float64(arg.Value))} + case *object.Float: + return &object.Float{Value: math.Sqrt(arg.Value)} + default: + return &object.Error{Message: "Hoja lazima iwe namba"} + } +} + +func cbrt(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.INTEGER_OBJ && args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe namba"} + } + switch arg := args[0].(type) { + case *object.Integer: + return &object.Float{Value: math.Cbrt(float64(arg.Value))} + case *object.Float: + return &object.Float{Value: math.Cbrt(arg.Value)} + default: + return &object.Error{Message: "Hoja lazima iwe namba"} + } +} + +func root(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 2 { + return &object.Error{Message: "Undo hili linahitaji hoja mbili tu"} + } + if args[0].Type() != object.INTEGER_OBJ && args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja ya kwanza lazima iwe namba"} + } + if args[1].Type() != object.INTEGER_OBJ { + return &object.Error{Message: "Hoja ya pili lazima iwe namba"} + } + base, ok := args[0].(*object.Float) + if !ok { + base = &object.Float{Value: float64(args[0].(*object.Integer).Value)} + } + exp := args[1].(*object.Integer).Value + + if exp == 0 { + return &object.Float{Value: 1.0} + } else if exp < 0 { + return &object.Error{Message: "Second Hoja lazima iwe a non-negative integer"} + } + + x := 1.0 + for i := 0; i < 10; i++ { + x = x - (math.Pow(x, float64(exp))-base.Value)/(float64(exp)*math.Pow(x, float64(exp-1))) + } + + return &object.Float{Value: x} +} + +func hypot(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) < 2 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + var sumOfSquares float64 + for _, arg := range args { + if arg.Type() != object.INTEGER_OBJ && arg.Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima ziwe namba"} + } + switch num := arg.(type) { + case *object.Integer: + sumOfSquares += float64(num.Value) * float64(num.Value) + case *object.Float: + sumOfSquares += num.Value * num.Value + } + } + return &object.Float{Value: math.Sqrt(sumOfSquares)} +} + +func factorial(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.INTEGER_OBJ { + return &object.Error{Message: "Hoja lazima iwe namba"} + } + n := args[0].(*object.Integer).Value + if n < 0 { + return &object.Error{Message: "Hoja lazima iwe a non-negative integer"} + } + result := int64(1) + for i := int64(2); i <= n; i++ { + result *= i + } + return &object.Integer{Value: result} +} + +func round(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + + num := args[0].(*object.Float).Value + return &object.Integer{Value: int64(num + 0.5)} +} + +func max(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + + arg, ok := args[0].(*object.Array) + if !ok { + return &object.Error{Message: "Hoja lazima iwe an array"} + } + + if len(arg.Elements) == 0 { + return &object.Error{Message: "Orodha haipaswi kuwa tupu"} + } + + var maxNum float64 + + for _, element := range arg.Elements { + if element.Type() != object.INTEGER_OBJ && element.Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Vipengee vya orodha lazima viwe namba"} + } + + switch num := element.(type) { + case *object.Integer: + if float64(num.Value) > maxNum { + maxNum = float64(num.Value) + } + case *object.Float: + if num.Value > maxNum { + maxNum = num.Value + } + default: + return &object.Error{Message: "Vipengee vya orodha lazima viwe namba"} + } + } + + return &object.Float{Value: maxNum} +} + +func min(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + + arg, ok := args[0].(*object.Array) + if !ok { + return &object.Error{Message: "Hoja lazima iwe an array"} + } + + if len(arg.Elements) == 0 { + return &object.Error{Message: "Orodha haipaswi kuwa tupu"} + } + + minNum := math.MaxFloat64 + + for _, element := range arg.Elements { + if element.Type() != object.INTEGER_OBJ && element.Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Vipengee vya orodha lazima viwe namba"} + } + + switch num := element.(type) { + case *object.Integer: + if float64(num.Value) < minNum { + minNum = float64(num.Value) + } + case *object.Float: + if num.Value < minNum { + minNum = num.Value + } + default: + return &object.Error{Message: "Vipengee vya orodha lazima viwe namba"} + } + } + + return &object.Float{Value: minNum} +} + +func exp(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Exp(num)} +} + +func expm1(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Expm1(num)} +} + +func log(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Log(num)} +} + +func log10(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Log10(num)} +} + +func log2(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.INTEGER_OBJ && args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe namba"} + } + + arg := extractFloatValue(args[0]) + + if arg <= 0 { + return &object.Error{Message: "Hoja lazima iwe kubwa kuliko 0"} + } + + return &object.Float{Value: math.Log2(arg)} +} + +func extractFloatValue(obj object.Object) float64 { + switch obj := obj.(type) { + case *object.Integer: + return float64(obj.Value) + case *object.Float: + return obj.Value + default: + return 0 + } +} + +func log1p(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Log1p(num)} +} + +func cos(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Cos(num)} +} + +func sin(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Sin(num)} +} + +func tan(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Tan(num)} +} + +func acos(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Acos(num)} +} + +func asin(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Asin(num)} +} + +func atan(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Atan(num)} +} + +func cosh(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Cosh(num)} +} + +func sinh(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Sinh(num)} +} + +func tanh(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Tanh(num)} +} + +func acosh(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Acosh(num)} +} + +func asinh(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Asinh(num)} +} + +func atan2(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 2 { + return &object.Error{Message: "Undo hili linahitaji hoja mbili tu."} + } + if args[0].Type() != object.INTEGER_OBJ && args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima ziwe namba"} + } + if args[1].Type() != object.INTEGER_OBJ && args[1].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima ziwe namba"} + } + + y := extractFloatValue(args[0]) + x := extractFloatValue(args[1]) + + return &object.Float{Value: math.Atan2(y, x)} +} + +func atanh(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Atanh(num)} +} \ No newline at end of file diff --git a/module/module.go b/module/module.go index e514a87..a82862a 100644 --- a/module/module.go +++ b/module/module.go @@ -9,4 +9,5 @@ func init() { Mapper["muda"] = &object.Module{Name: "time", Functions: TimeFunctions} Mapper["mtandao"] = &object.Module{Name: "net", Functions: NetFunctions} Mapper["jsoni"] = &object.Module{Name: "json", Functions: JsonFunctions} + Mapper["hisabati"] = &object.Module{Name: "hisabati", Functions: MathFunctions} } diff --git a/repl/docs/en/README.md b/repl/docs/en/README.md index e34c64d..ae3e1c8 100644 --- a/repl/docs/en/README.md +++ b/repl/docs/en/README.md @@ -69,6 +69,10 @@ This documentation is intended for people with some experience in programming. I - [Import JSONI](json.md#import-jsoni) - [Decoding JSON with dikodi()](json.md#decoding-json-with-dikodi()) - [Encoding JSON with enkodi()](json.md#encoding-json-with-enkodi()) +- [Hisabati in nuru](hisabati.md#module-hisabati) + - [Import Hisabati](hisabati.md#usage) + - [In-built Constants](hisabati.md#1-constants) + - [In-built Methods](hisabati.md#2-methods) - [KEYWORDS](keywords.md#keywords) - [Reserved Keywords](keywords.md#reserved-keywords) - [BuiltIns](keywords.md#builtins) diff --git a/repl/docs/en/hisabati.md b/repl/docs/en/hisabati.md new file mode 100644 index 0000000..b8f4afb --- /dev/null +++ b/repl/docs/en/hisabati.md @@ -0,0 +1,257 @@ +# Module Hisabati + +Module Hisabati is a inbuilt math module by [VictorKariuki](https://github.com/VictorKariuki). + +This in-built module provides various mathematical functions and constants. It includes methods for `trigonometric functions`, `logarithmic functions`, `array operations`, and `utility functions`. + +## Usage + +To use the `hisabati` in-built module follow the steps below: + +1. You directly import the `hisabati` in-built module and any required in-built modules in your Nuru code using the `tumia` keyword. + + ```nuru + tumia hisabati + ``` + +2. Calling the in-built module methods: + + ```nuru + andika(hisabati.e()) + ``` + +## Yaliyomo + +This in-built module covers a wide range of mathematical operations, including : + +- `Basic Mathematical Functions:` +- `Hyperbolic` & `Trigonometric Functions` +- `Exponential` & `Logarithmic Functions` +- `Rounding` & `Comparison Functions` + +Here is an in-depth classification of the methods: + +1. Trigonometric Functions: + + - `cos(n)` + - `sin(n)` + - `tan(n)` + - `acos(n)` + - `asin(n)` + - `atan(n)` + - `hypot(numbers)` + +2. Hyperbolic Functions: + + - `cosh(n)` + - `sinh(n)` + - `tanh(n)` + - `acosh(n)` + - `asinh(n)` + - `atanh(n)` + +3. Exponential and Logarithmic Functions: + + - `exp(n)` + - `expm1(n)` + - `log(n)` + - `log2(n)` + - `log10(n)` + - `log1p(n)` + +4. Basic Mathematical Functions: + + - `abs(n)` + - `sqrt(n)` + - `cbrt(n)` + - `root(x, n)` + - `factorial(n)` + - `sign(n)` + +5. Rounding and Comparison Functions: + + - `ceil(n)` + - `floor(n)` + - `round(n)` + - `max(numbers)` + - `min(numbers)` + +### 1. Constants: + +- **PI**: Represents the mathematical constant `π`. +- **e**: Represents `Euler's Number`. +- **phi**: Represents the `Golden Ratio`. +- **ln10**: Represents the `natural logarithm of 10`. +- **ln2**: Represents the `natural logarithm of 2`. +- **log10e**: Represents the `base 10 logarithms` of Euler's number `(e)`. +- **log2e**: Represents the `base 2 logarithm` of Euler's number` (e)`. +- **sqrt1_2**: Represents the `square root` of `1/2`. +- **sqrt2**: Represents the `square root` of `2`. +- **sqrt3**: Represents the `square root` of `3`. +- **sqrt5**: Represents the `square root` of `5`. +- **EPSILON**: Represents a small value `2.220446049250313e-16`. + +### 2. Methods: + +1. **abs(namba)** + + - Description: Calculates the absolute value of a number. + - Example: `hisabati.abs(-42)` returns `42`. + +2. **acos(n)** + + - Description: Calculates the arccosine of a number. + - Example: `hisabati.acos(0.5)` returns `1.0471975511965979`. + +3. **acosh(n)** + + - Description: Calculates the inverse hyperbolic cosine of a number. + - Example: `hisabati.acosh(2.0)` returns `1.3169578969248166`. + +4. **asin(n)** + + - Description: Calculates the arcsine of a number using the Taylor series. + - Example: `hisabati.arcsin(0.5)` returns `0.5235987755982988`. + +5. **asinh(n)** + + - Description: Calculates the inverse hyperbolic sine of a number. + - Example: `hisabati.arsinh(2.0)` returns `1.4436354751788103`. + +6. **atan(n)** + + - Description: Calculates the arctangent of a number using the Taylor series. + - Example: `hisabati.atan(1.0)` returns `0.7853981633974483`. + +7. **atan2(y, x)** + + - Description: Calculates the arctangent of the quotient of its arguments. + - Example: `hisabati.atan2(1.0, 1.0)` returns `0.7853981633974483`. + +8. **atanh(n)** + + - Description: Calculates the inverse hyperbolic tangent of a number. + - Example: `hisabati.atanh(0.5)` returns `0.5493061443340549`. + +9. **cbrt(n)** + + - Description: Calculates the cube root of a number. + - Example: `hisabati.cbrt(8)` returns `2`. + +10. **root(x, n)** + + - Description: Calculates the nth root of a number using the Newton-Raphson method. + - Example: `hisabati.root(27, 3)` returns `3`. + +11. **ceil(n)** + + - Description: Rounds up to the smallest integer greater than or equal to a given number. + - Example: `hisabati.ceil(4.3)` returns `5`. + +12. **cos(n)** + + - Description: Calculates the cosine of an angle in radians using the Taylor series. + - Example: `hisabati.cos(0.0)` returns `1`. + +13. **cosh(n)** + + - Description: Calculates the hyperbolic cosine of a number. + - Example: `hisabati.cosh(0.0)` returns `1`. + +14. **exp(n)** + + - Description: Calculates the value of Euler's number raised to the power of a given number. + - Example: `hisabati.exp(2.0)` returns `7.38905609893065`. + +15. **expm1(n)** + + - Description: Calculates Euler's number raised to the power of a number minus 1. + - Example: `hisabati.expm1(1.0)` returns `1.718281828459045`. + +16. **floor(n)** + + - Description: Rounds down to the largest integer less than or equal to a given number. + - Example: `hisabati.floor(4.7)` returns `4`. + +17. **hypot(values)** + + - Description: Calculates the square root of the sum of squares of the given values. + - Example: `hisabati.hypot([3, 4])` returns `5`. + +18. **log(n)** + + - Description: Calculates the natural logarithm of a number. + - Example: `hisabati.log(1.0)` returns `0`. + +19. **log10(n)** + + - Description: Calculates the base 10 logarithm of a number. + - Example: `hisabati.log10(100.0)` returns `2`. + +20. **log1p(n)** + + - Description: Calculates the natural logarithm of 1 plus the given number. + - Example: `hisabati.log1p(1.0)` returns `0.6931471805599453`. + +21. **log2(n)** + + - Description: Calculates the base 2 logarithm of a number. + - Example: `hisabati.log2(8)` returns `3`. + +22. **max(numbers)** + + - Description: Finds the maximum value in a list of numbers. + - Example: `hisabati.max([4, 2, 9, 5])` returns `9`. + +23. **min(numbers)** + + - Description: Finds the minimum value in a list of numbers. + - Example: `hisabati.min([4, 2, 9, 5])` returns `2`. + +24. **round(x, method)** + + - Description: Rounds a number to the nearest integer using the specified method. + - Example: `hisabati.round(4.6)` returns `5`. + +25. **sign(n)** + + - Description: Determines the sign of a number. + - Example: `hisabati.sign(-5)` returns `-1`. + +26. **sin(n)** + + - Description: Calculates the sine of an angle in radians using the Taylor series. + - Example: `hisabati.sin(1.0)` returns `0.8414709848078965`. + +27. **sinh(n)** + + - Description: Calculates the hyperbolic sine of a number. + - Example: `hisabati.sinh(1.0)` returns `1.1752011936438014`. + +28. **sqrt(n)** + + - Description: Calculates the square root of a number. + - Example: `hisabati.sqrt(4)` returns `2`. + +29. **tan(n)** + + - Description: Calculates the tangent of an angle in radians. + - Example: `hisabati.tan(1.0)` returns `1.557407724654902`. + +30. **tanh(n)** + + - Description: Calculates the hyperbolic tangent of a number. + - Example: `hisabati.tanh(1.0)` returns `0.7615941559557649`. + +31. **factorial(n)** + + - Description: Calculates the factorial of a number. + - Example: `hisabati.factorial(5)` returns `120`. + +### Contributing + +Contributions to the `module hisabati` are welcome. If you have any improvements or bug fixes, feel free to create a pull request. + +### License + +This in-built module is available under the MIT License. See the [LICENSE](LICENSE) file for more information. \ No newline at end of file diff --git a/third_party/math/README.md b/third_party/math/README.md index 911f157..08a2e38 100644 --- a/third_party/math/README.md +++ b/third_party/math/README.md @@ -1,30 +1,29 @@ -# Pakeji Hisabati (Math Package) +# Pakeji Hesabu (Math Package) -Pakeji Hisabati is a math package written in pure Nuru by [VictorKariuki](https://github.com/VictorKariuki). +Pakeji Hesabu is a math package written in pure Nuru by [VictorKariuki](https://github.com/VictorKariuki). This package provides various mathematical functions and constants implemented in nuru programming language. It includes methods for `trigonometric functions`, `logarithmic functions`, `array operations`, and `utility functions`. ## Usage -To use the `pakeji hisabati` package follow the steps below: +To use the `pakeji hesabu` package follow the steps below: -1. Copy the `hisabati.nr` file and any required third-party package files into the same directory as your project. +1. Copy the `hesabu.nr` file and any required third-party package files into the same directory as your project. -2. Ensure that the package file names end with the `.nr` extension and match the package names. For example, if the package name is `hisabati`, the corresponding file name should be `hisabati.nr`. +2. Ensure that the package file names end with the `.nr` extension and match the package names. For example, if the package name is `hesabu`, the corresponding file name should be `hesabu.nr`. -3. You can directly import the `hisabati.nr` package and any required third-party packages in your Nuru code using the `tumia` keyword. For example: +3. You can directly import the `hesabu.nr` package and any required third-party packages in your Nuru code using the `tumia` keyword. For example: ```nuru - tumia "hisabati" + tumia "hesabu" ``` Example of calling the package methods: ```nuru - andika(hisabati.e()) - + andika(hesabu.e()) ## What is in This package covers a wide range of mathematical operations, including `basic arithmetic`, `trigonometry`, `exponential and logarithmic functions`, `rounding and comparison operations`, as well as some `utility and array operations`. -The methods provided in the `hisabati` package can be classified into different categories based on their functionalities. Here is a classification of the methods: +The methods provided in the `hesabu` package can be classified into different categories based on their functionalities. Here is a classification of the methods: 1. Trigonometric Functions: - `cos(x)` @@ -93,152 +92,161 @@ The methods provided in the `hisabati` package can be classified into different 1. **abs(namba)** - Description: Calculates the absolute value of a number. - - Example: `hisabati.abs(-42)` returns `42`. + - Example: `hesabu.abs(-42)` returns `42`. 2. **acos(x)** - Description: Calculates the arccosine of a number. - - Example: `hisabati.acos(0.5)` returns `1.0471975511965979`. + - Example: `hesabu.acos(0.5)` returns `1.0471975511965979`. 3. **acosh(x)** - Description: Calculates the inverse hyperbolic cosine of a number. - - Example: `hisabati.acosh(2)` returns `1.3169578969248166`. + - Example: `hesabu.acosh(2)` returns `1.3169578969248166`. -4. **arcsin(x)** +4. **asin(x)** - Description: Calculates the arcsine of a number using the Taylor series. - - Example: `hisabati.arcsin(0.5)` returns `0.5235987755982988`. + - Example: `hesabu.arcsin(0.5)` returns `0.5235987755982989`. -5. **arsinh(x)** +5. **asinh(x)** - Description: Calculates the inverse hyperbolic sine of a number. - - Example: `hisabati.arsinh(2)` returns `1.4436354751788103`. + - Example: `hesabu.arsinh(2)` returns `1.4436354751788103`. 6. **atan(x)** - Description: Calculates the arctangent of a number using the Taylor series. - - Example: `hisabati.atan(1)` returns `0.7853981633974483`. + - Example: `hesabu.atan(1)` returns `0.7853981633974485`. 7. **atan2(y, x)** - Description: Calculates the arctangent of the quotient of its arguments. - - Example: `hisabati.atan2(1, 1)` returns `0.7853981633974483`. + - Example: `hesabu.atan2(1, 1)` returns `0.7853981633974483`. 8. **atanh(x)** - Description: Calculates the inverse hyperbolic tangent of a number. - - Example: `hisabati.atanh(0.5)` returns `0.5493061443340549`. + - Example: `hesabu.atanh(0.5)` returns `0.5493061443340549`. 9. **cbrt(x)** - Description: Calculates the cube root of a number. - - Example: `hisabati.cbrt(8)` returns `2`. + - Example: `hesabu.cbrt(8)` returns `2`. 10. **root(x, n)** - Description: Calculates the nth root of a number using the Newton-Raphson method. - - Example: `hisabati.root(27, 3)` returns `3`. + - Example: `hesabu.root(27, 3)` returns `3`. 11. **ceil(x)** - Description: Rounds up to the smallest integer greater than or equal to a given number. - - Example: `hisabati.ceil(4.3)` returns `5`. + - Example: `hesabu.ceil(4.3)` returns `5`. 12. **cos(x)** - Description: Calculates the cosine of an angle in radians using the Taylor series. - - Example: `hisabati.cos(0)` returns `1`. + - Example: `hesabu.cos(5)` returns `0.28366218546322464`. 13. **cosh(x)** - Description: Calculates the hyperbolic cosine of a number. - - Example: `hisabati.cosh(0)` returns `1`. + - Example: `hesabu.cosh(5)` returns `74.20994842490012`. 14. **exp(x)** - Description: Calculates the value of Euler's number raised to the power of a given number. - - Example: `hisabati.exp(2)` returns `7.38905609893065`. + - Example: `hesabu.exp(2)` returns `7.389056098930649`. 15. **expm1(x)** - Description: Calculates Euler's number raised to the power of a number minus 1. - - Example: `hisabati.expm1(1)` returns `1.718281828459045`. + - Example: `hesabu.expm1(1)` returns `1.7182818284590455`. 16. **floor(x)** - Description: Rounds down to the largest integer less than or equal to a given number. - - Example: `hisabati.floor(4.7)` returns `4`. + - Example: `hesabu.floor(4.7)` returns `4`. 17. **hypot(values)** - Description: Calculates the square root of the sum of squares of the given values. - - Example: `hisabati.hypot([3, 4])` returns `5`. + - Example: `hesabu.hypot([3, 4])` returns `5`. 18. **log(x)** - Description: Calculates the natural logarithm of a number. - - Example: `hisabati.log(1)` returns `0`. + - Example: `hesabu.log(2)` returns `0.69314718056`. 19. **log10(x)** - Description: Calculates the base 10 logarithm of a number. - - Example: `hisabati.log10(100)` returns `2`. + - Example: `hesabu.log10(100)` returns `1.9999999999573126`. 20. **log1p(x)** - Description: Calculates the natural logarithm of 1 plus the given number. - - Example: `hisabati.log1p(1)` returns `0.6931471805599453`. + - Example: `hesabu.log1p(1)` returns `0.6931471805599451`. 21. **log2(x)** - Description: Calculates the base 2 logarithm of a number. - - Example: `hisabati.log2(8)` returns `3`. + - Example: `hesabu.log2(8)` returns `3`. 22. **max(numbers)** - Description: Finds the maximum value in a list of numbers. - - Example: `hisabati.max([4, 2, 9, 5])` returns `9`. + - Example: `hesabu.max([4, 2, 9, 5])` returns `9`. 23. **min(numbers)** - Description: Finds the minimum value in a list of numbers. - - Example: `hisabati.min([4, 2, 9, 5])` returns `2`. + - Example: `hesabu.min([4, 2, 9, 5])` returns `2`. 24. **round(x, method)** - Description: Rounds a number to the nearest integer using the specified method. - - Example: `hisabati.round(4.6, "rpi")` returns `5`. + - supported methods: + - "rpi" (round to the nearest integer using the principle of rounding half to the nearest even) + - "rni" (round to the nearest integer using the principle of rounding half away from zero) + - "ri" (round to the nearest integer using the standard rounding method) + - An invalid method results in returning NaN (Not a Number) + - Example: `hesabu.round(4.6, "rpi")` returns `5`. 25. **sign(x)** - Description: Determines the sign of a number. - - Example: `hisabati.sign(-5)` returns `-1`. + - Example: `hesabu.sign(-5)` returns `-1`. 26. **sin(x)** - Description: Calculates the sine of an angle in radians using the Taylor series. - - Example: `hisabati.sin(0)` returns `0`. + - Example: `hesabu.sin(1)` returns `0.8414709848078965`. 27. **sinh(x)** - Description: Calculates the hyperbolic sine of a number. - - Example: `hisabati.sinh(0)` returns `0`. + - Example: `hesabu.sinh(0)` returns `0`. 28. **sqrt(x)** - Description: Calculates the square root of a number. - - Example: `hisabati.sqrt(4)` returns `2`. + - Example: `hesabu.sqrt(4)` returns `2`. 29. **tan(x)** - Description: Calculates the tangent of an angle in radians. - - Example: `hisabati.tan(0)` returns `0`. + - Example: `hesabu.tan(1)` returns `1.557407724654902`. 30. **tanh(x)** - Description: Calculates the hyperbolic tangent of a number. - - Example: `hisabati.tanh(0)` returns `0`. + - Example: `hesabu.tanh(0)` returns `0`. 31. **factorial(n)** - Description: Calculates the factorial of a number. - - Example: `hisabati.factorial(5)` returns `120`. + - Example: `hesabu.factorial(5)` returns `120`. 32. **isNegative(num)** - Description: Checks if a number is negative. - - Example: `hisabati.isNegative(-5)` returns `true`. + - Example: `hesabu.isNegative(-5)` returns `kweli`. 33. **isInteger(num)** - Description: Checks if a number is an integer. - - Example: `hisabati.isInteger(4.5)` returns `false`. + - Example: `hesabu.isInteger(4.5)` returns `sikweli`. 34. **getIntegerPart(num)** - Description: Gets the integer part of a number. - - Example: `hisabati.getIntegerPart(4.5)` returns `4`. + - Example: `hesabu.getIntegerPart(4.5)` returns `4`. 35. **list(first, last, interval)** - Description: Creates a list of numbers with the specified interval between them. - - Example: `hisabati.list(1, 5, 1)` returns `[1, 2, 3, 4]`. + - Example: `hesabu.list(1, 5, 1)` returns `[1, 2, 3, 4]`. 36. **reduce(iterator, callback, initialValue)** - Description: Reduces the elements of an array to a single value using a specified callback function. - - Example: `hisabati.reduce([1, 2, 3, 4], (accumulator, currentValue) => accumulator + currentValue, 0)` returns `10`. - + - Example: `hesabu.reduce([1, 2, 3, 4], [callback function], 0)` + ```s + fanya callback = unda(accumulator, currentValue){ + rudisha accumulator + currentValue; + } + andika(hesabu.reduce([1, 2, 3, 4], callback, 0)) \\ returns 10. ### Contributing -Contributions to the `pakeji hisabati` package are welcome. If you have any improvements or bug fixes, feel free to create a pull request. +Contributions to the `pakeji hesabu` package are welcome. If you have any improvements or bug fixes, feel free to create a pull request. ### License diff --git a/third_party/math/hisabati.nr b/third_party/math/hesabu.nr similarity index 58% rename from third_party/math/hisabati.nr rename to third_party/math/hesabu.nr index 2691b19..ec113c8 100644 --- a/third_party/math/hisabati.nr +++ b/third_party/math/hesabu.nr @@ -1,4 +1,6 @@ -pakeji hisabati{ +tumia hisabati + +pakeji hesabu{ //CONSTRUCTOR METHOD andaa = unda() {} @@ -60,7 +62,7 @@ pakeji hisabati{ // @.EPSILON EPSILON = unda() { - rudisha 2.220446049250313e-16; + rudisha 0.0000000000000002220446049250313; } // Methods @@ -75,27 +77,25 @@ pakeji hisabati{ //acos(x), calculates the arccosine of a number. acos = unda(x) { - kama(x < -1 || x > 1) { - rudisha 0; + kama (x < -1 || x > 1) { + rudisha "NaN"; } - // Define the precision for the approximation. - fanya precision = 1e-10; - - // Initial guess for the angle in radians (between 0 and π). - fanya angle = @.PI / 4; + fanya EPSILON = 1*10.0**-10; // Small value for precision - wakati(true) { - fanya cosAngle = @.cos(angle); - fanya error = @.abs(cosAngle - x); + fanya acosRecursive = unda(guess) { + fanya f = cos(guess) - x; + fanya fPrime = -sin(guess); + fanya nextGuess = guess - f / fPrime; - kama(error < precision) { - rudisha angle; + kama (abs(nextGuess - guess) < EPSILON) { + rudisha nextGuess; } - // Update the angle using the Newton-Raphson method. - angle -= (cosAngle - x) / (-@.sin(angle)); + rudisha acosRecursive(nextGuess); } + + rudisha acosRecursive(hisabati.PI() / 2); // Initial guess for acos } //acosh(x), calculates the inverse hyperbolic cosine of a number. @@ -104,90 +104,75 @@ pakeji hisabati{ rudisha 0; } - rudisha @.log(x + @.sqrt(x * x - 1)); + rudisha log(x + sqrt(x * x - 1)); } - //arcsin(x), calculates the arcsine of a number using the Taylor series. - arcsin = unda(x) { - kama(x < -1 || x > 1) { - rudisha 0; + //asin(x), calculates the arcsine of a number using the Newton Method. + asin = unda(x) { + kama (x < -1 || x > 1) { + rudisha "NaN"; } fanya maxIterations = 50; // Maximum number of iterations - fanya result = 0; - fanya n = 0; - wakati(n < maxIterations) { - fanya numerator = (-1) ** n * x ** (2 * n + 1); - fanya denominator = @.factorial(2 * n + 1); // You'll need to implement a factorial function + fanya newtonAsin = unda(guess, prev, iterations) { + fanya next = guess - (sin(guess) - x) / cos(guess); + + kama (abs(next - prev) < hisabati.EPSILON() || iterations >= maxIterations) { + rudisha next; + } - result += numerator / denominator; - n++; + rudisha newtonAsin(next, guess, iterations + 1); } - rudisha result; + rudisha newtonAsin(x, 1, 0); } - //arsinh(x), calculates the inverse hyperbolic sine of a number. - arsinh = unda(x) { + + //asinh(x), calculates the inverse hyperbolic sine of a number. + asinh = unda(x) { // Calculate arsinh using the formula: arsinh(x) = ln(x + sqrt(x^2 + 1)) kama(x >= 0) { - rudisha @.log(x + @.sqrt(x * x + 1)); + rudisha log(x + sqrt(x * x + 1)); } sivyo { // For negative values, arsinh(x) = -arsinh(-x) - rudisha - @.log(-x + @.sqrt(x * x + 1)); + rudisha - log(-x + sqrt(x * x + 1)); } } //atan(x), calculates the arctangent of a number using the Taylor series. atan = unda(x) { - kama(x == 0) { - rudisha 0; - } // arctan(0) is 0 - kama(x == Infinity) { - rudisha @.PI / 2; - } - kama(x == -Infinity) { - rudisha - @.PI / 2; - } // arctan(-Infinity) is -π/2 + fanya EPSILON = 1*10.0**-10; // Small value for precision - // Use the Taylor series expansion for arctan(x) - // arctan(x) = x - (x^3) / 3 + (x^5) / 5 - (x^7) / 7 + ... - fanya n = 3; - fanya result = 0; - fanya term = x * x; - fanya sign = -1; - - wakati(true) { - fanya currentTerm = sign * (term / n); + fanya atanRecursive = unda(guess) { + fanya f = tan(guess) - x; + fanya fPrime = 1 / (cos(guess) * cos(guess)); + fanya nextGuess = guess - f / fPrime; - kama(currentTerm == 0) { - vunja + kama (abs(nextGuess - guess) < EPSILON) { + rudisha nextGuess; } - result += currentTerm; - n += 2; - sign = -sign; - term *= x * x; + rudisha atanRecursive(nextGuess); } - rudisha result; + rudisha atanRecursive(x); // Initial guess for atan } //atanh(x), calculates the inverse hyperbolic tangent of a number. atan2 = unda(y, x) { kama(x > 0) { - rudisha @.atan(y / x); + rudisha atan(y / x); } au kama(x < 0 && y >= 0) { - rudisha @.atan(y / x) + @.PI; + rudisha atan(y / x) + hisabati.PI(); } au kama(x < 0 && y < 0) { - rudisha @.atan(y / x) - @.PI; + rudisha atan(y / x) - hisabati.PI(); } au kama(x == 0 && y > 0) { - rudisha @.PI / 2; + rudisha hisabati.PI() / 2; } au kama(x == 0 && y < 0) { - rudisha - @.PI / 2; + rudisha - hisabati.PI() / 2; } au kama(x == 0 && y == 0) { - rudisha NaN; // Undefined + rudisha "NaN"; // Undefined } } @@ -196,30 +181,35 @@ pakeji hisabati{ kama(x < -1 || x > 1) { rudisha 0; } - rudisha 0.5 * @.log((1 + x) / (1 - x)); + rudisha 0.5 * log((1.0 + x) / (1.0 - x)); } //cbrt(x), calculates the cube root of a number. cbrt = unda(x) { + kama(x == 0) { + rudisha 0; + } + kama(x >= 0) { - rudisha @.root(x, 3); + rudisha root(x, 3); } sivyo { - rudisha - @.root(-x, 3); + rudisha - root(-x, 3); } } //root(x, n), calculates the nth root of a number using the Newton-Raphson method. - root = unda(x, n) { + root = unda(x, n) { fanya guess = x / 2; // Initial guess - fanya tolerance = 1e-10; // Tolerance for convergence + fanya tolerance = 0.0000000001; // Tolerance for convergence - wakati(true) { - fanya nextGuess = ((n - 1) * guess + x / guess ** n - 1) / n; - kama(@.abs(nextGuess - guess) < tolerance) { - rudisha nextGuess; - } - guess = nextGuess; + fanya calculateNthRoot = unda(x, n, guess, tolerance) { + fanya nextGuess = ((n - 1) * guess + x / (guess ** (n - 1))) / n; + fanya ipotolerance = abs(nextGuess - guess); + kama (ipotolerance < tolerance) {rudisha nextGuess}; + rudisha calculateNthRoot(x, n, nextGuess, tolerance); } + + rudisha calculateNthRoot(x, n, guess, tolerance) } //ceil(x), rounds up to the smallest integer greater than or equal to a given number. @@ -234,70 +224,53 @@ pakeji hisabati{ } } - //cos(x), calculates the cosine of an angle in radians using the Taylor series. - cos = unda(x, terms = 10) { - // Initialize the result - fanya n = 0; - fanya result = 0; - - wakati(n < terms) { - // Calculate the numerator and denominator for the nth term - fanya numerator = 0; - kama(n % 2 == 0) { - numerator = x ** (2 * n + 1); - } sivyo { - numerator = -x ** (2 * n + 1); - } - fanya denominator = @.factorial(2 * n); - - // Add the nth term to the result - result += numerator / denominator; + //cos(x), calculates the cosine of an angle. + cos = unda(x) { + fanya result = 1; // Initialize the result + fanya term = 1; - n++; + kwa i ktk list(2,101,2) { + term = (-term * x * x) / (i * (i - 1)); + result += term; } - rudisha result; } //cosh(x), calculates the hyperbolic cosine of a number. cosh = unda(x) { - fanya eToX = @.exp(x); - fanya eToMinusX = @.exp(-x); + fanya eToX = exp(x); + fanya eToMinusX = exp(-x); rudisha(eToX + eToMinusX) / 2; } //exp(x), calculates the value of Euler's number raised to the power of a given number. - exp = unda(x, precision = 15) { + exp = unda(n) { fanya result = 1; fanya term = 1; - fanya i = 1; - - wakati(i <= precision) { - term *= x / i; - result += term; - i++; + + kwa i, v ktk list(1,23,1) { + term = term*(n/v); + result = result + term; } - rudisha result; } + //expm1(x), calculates the value of Euler's number raised to the power of a given number minus 1. expm1 = unda(x) { - fanya epsilon = 1e-15; // A small value to improve accuracy - fanya result = 0; - fanya term = x; - fanya n = 1; - - wakati(@.abs(term) > epsilon) { - result += term; - n++; - term *= x / n; + kama (x == -1) { + rudisha -0.6321205588285577; // Handling the special case for -1 + } au kama (x == 0) { + rudisha 0; // Handling the special case for 0 + } au kama (abs(x) < hisabati.EPSILON()) { + rudisha x + 0.5 * x * x; // Approximation for very small x + } sivyo { + rudisha exp(x) - 1; } - - rudisha result; } + //floor(x), rounds down to the largest integer less than or equal to a given number. floor = unda(x) { kama(x >= 0) { @@ -314,31 +287,33 @@ pakeji hisabati{ rudisha acc + value ** 2; } - fanya sumOfSquares = @.reduce(values, exp, 0); + fanya sumOfSquares = reduce(values, exp, 0); // Calculate the square root of the sum of squares - fanya result = @.sqrt(sumOfSquares); + fanya result = sqrt(sumOfSquares); rudisha result; } //log(x), calculates the natural logarithm of a number. log = unda(x) { - kama(x <= 0) { + kama (x <= 0) { + rudisha "NaN"; + } + kama (x == 1) { rudisha 0; } - - fanya approx = 0; - fanya n = 50; - fanya i = 1; - - wakati(i <= n) { - approx += (1 / i) * ((x - 1) / (x + 1)) ** (2 * i - 1); - i++; + kama (x < 0) { + rudisha -log(-x); } - - - rudisha 2 * approx; + fanya n = 1000; // Number of iterations + fanya y = (x - 1) / (x + 1); + fanya ySquared = y * y; + fanya result = 0; + kwa i ktk list(1,n+1,2) { + result += (1 / i) * y**i; + } + rudisha 2 * result; } //log10(x), calculates the base 10 logarithm of a number. @@ -348,39 +323,18 @@ pakeji hisabati{ } // Calculate natural logarithm and divide by the natural logarithm of 10 - rudisha this.log(x) / this.log(10); + rudisha log(x) / log(10.0); } //log1p(x), calculates the natural logarithm of 1 plus the given number. log1p = unda(x) { - kama(x < -1) { - rudisha 0; - } - - kama(x == -1) { - rudisha(-Infinity); - } - - kama(x == Infinity) { - rudisha Infinity; - } - - kama(x == 0) { - rudisha 0; - } - - // Use the formula: ln(1 + x) = x - (x^2)/2 + (x^3)/3 - (x^4)/4 + ... - fanya result = 0; - fanya term = x; - fanya i = 2; - - wakati(@.abs(term) > @.EPSILON) { - result += term; - term *= -x / i; - i++; + kama (x <= -1) { + rudisha NaN; // Not a Number + } au kama (abs(x) < hisabati.EPSILON()) { + rudisha x - 0.5 * x * x; // Series expansion for small x + } sivyo { + rudisha log(1.0 + x); } - - rudisha result; } //log2(x), calculates the base 2 logarithm of a number. @@ -403,7 +357,7 @@ pakeji hisabati{ //max(numbers), finds the maximum value in a list of numbers. max = unda(numbers) { // Initialize a variable to store the largest number - fanya largest = -Infinity; + fanya largest = 0; // Iterate through the numbers and update 'largest' kama a larger number is found kwa num ktk numbers { @@ -412,20 +366,20 @@ pakeji hisabati{ } } - // rudisha the largest number (or -Infinity kama there are no parameters) + // rudisha the largest number (or 0 kama there are no parameters) rudisha largest; } //min(numbers), finds the minimum value in a list of numbers. min = unda(numbers) { - kama(numbers.length == 0) { - rudisha Infinity; + kama(numbers.idadi() == 0) { + rudisha 0; } fanya minVal = numbers[0]; fanya i = 1; - wakati(i < numbers.length) { + wakati(i < numbers.idadi()) { kama(numbers[i] < minVal) { minVal = numbers[i]; } @@ -464,36 +418,22 @@ pakeji hisabati{ } //sin(x), calculates the sine of an angle in radians using the Taylor series. - sin = unda(x, terms = 10) { - // Initialize the result - fanya n = 0; - fanya result = 0; - - wakati(n < terms) { - // Calculate the numerator and denominator for the nth term - fanya numerator = 0; - kama(n % 2 == 0) { - numerator = x ** (2 * n + 1); - } sivyo { - numerator = -x ** (2 * n + 1); - } - - fanya denominator = @.factorial(2 * n + 1); - - // Add the nth term to the result - result += numerator / denominator; - - n++; + sin = unda(x) { + fanya result = x; // Initialize the result with the angle + fanya term = x; + // Using Maclaurin series expansion for sine + kwa i ktk list(3,101,2) { + term = (-term * x * x) / (i * (i - 1)); + result += term; } - rudisha result; } //sinh(x), calculates the hyperbolic sine of a number. sinh = unda(x) { // sinh(x) = (e^x - e^(-x)) / 2 - fanya eToX = @.exp(x); - fanya eToMinusX = @.exp(-x); + fanya eToX = exp(x); + fanya eToMinusX = exp(-x); rudisha(eToX - eToMinusX) / 2; } @@ -502,27 +442,17 @@ pakeji hisabati{ kama(x < 0) { rudisha 0; } - - // Initial guess for the square root (you can choose a better initial guess) - fanya guess = x / 2; - fanya tolerance = 1e-7; // Tolerance for approximation - - wakati(true) { - fanya nextGuess = 0.5 * (guess + x / guess); - - // Check kama the guess is close enough to the actual square root - kama(@.abs(nextGuess - guess) < tolerance) { - rudisha nextGuess; - } - - guess = nextGuess; + kama(x >= 0) { + rudisha root(x, 2); + } sivyo { + rudisha - root(-x, 2); } } //tan(x), calculates the tangent of an angle in radians. tan = unda(x) { - fanya sineX = @.sine(x); - fanya cosineX = @.sqrt(1 - sineX * sineX); + fanya sineX = sin(x); + fanya cosineX = sqrt(1 - sineX * sineX); kama(cosineX == 0) { rudisha 0; @@ -533,15 +463,9 @@ pakeji hisabati{ //tanh(x), calculates the hyperbolic tangent of a number. tanh = unda(x) { - kama(x == Infinity) { - rudisha 1; - } au kama(x == -Infinity) { - rudisha - 1; - } sivyo { - fanya expX = @.exp(x); - fanya expNegX = @.exp(-x); - rudisha(expX - expNegX) / (expX + expNegX); - } + fanya expX = exp(x); + fanya expNegX = exp(-x); + rudisha(expX - expNegX) / (expX + expNegX); } // utility methods @@ -564,23 +488,23 @@ pakeji hisabati{ //isNegative(num), checks if a number is negative. isNegative = unda(num) { - rudisha num < 0; + rudisha sign(num)==-1; } //isInteger(num), checks if a number is an integer. isInteger = unda(num) { - rudisha num == @.floor(num); + rudisha num == floor(num); } //getIntegerPart(num), gets the integer part of a number. getIntegerPart = unda(num) { // Handle negative numbers separately - kama(@.isNegative(num)) { + kama(isNegative(num)) { // For negative numbers, we subtract the absolute value of the fractional part from 1 - rudisha - (@.ceil(-num) - 1); + rudisha - (ceil(-num) - 1); } sivyo { // For positive numbers, we simply truncate the fractional part - rudisha @.floor(num); + rudisha floor(num); } } diff --git a/third_party/math/test.nr b/third_party/math/test.nr new file mode 100644 index 0000000..29b9895 --- /dev/null +++ b/third_party/math/test.nr @@ -0,0 +1,41 @@ +tumia "hesabu" + +andika("abs: ",hesabu.abs(-42)); +andika("acos: ",hesabu.acos(0.5)); +andika("acosh: ",hesabu.acosh(2)); +andika("asin: ", hesabu.asin(0.5)); +andika("asinh: ",hesabu.asinh(2)); +andika("atan: ",hesabu.atan(1)); +andika("atan2: ",hesabu.atan2(1, 1)); +andika("atanh: ",hesabu.atanh(0.5)); +andika("cbrt: ",hesabu.cbrt(8)); +andika("root: ",hesabu.root(27, 3)); +andika("ceil: ",hesabu.ceil(4.3)); +andika("cos: ",hesabu.cos(5)); +andika("cosh: ",hesabu.cosh(5)); +andika("exp: ",hesabu.exp(2)); +andika("expm1: ",hesabu.expm1(1)); +andika("floor: ",hesabu.floor(4.7)); +andika("hypot: ",hesabu.hypot([3, 4])); +andika("log: ",hesabu.log(2)); +andika("log10: ",hesabu.log10(100)); +andika("log1p: ",hesabu.log1p(1)); +andika("log2: ",hesabu.log2(8)); +andika("max: ",hesabu.max([4, 2, 9, 5])); +andika("min: ",hesabu.min([4, 2, 9, 5])); +andika("round: ",hesabu.round(4.6, "rpi")); +andika("sign: ",hesabu.sign(-5)); +andika("sin: ",hesabu.sin(1)); +andika("sinh: ",hesabu.sinh(0)); +andika("sqrt: ",hesabu.sqrt(4)); +andika("tan: ",hesabu.tan(1)); +andika("tanh: ",hesabu.tanh(0)); +andika("factorial: ",hesabu.factorial(5)); +andika("isNegative: ",hesabu.isNegative(-5)); +andika("isInteger: ",hesabu.isInteger(4.5)); +andika("getIntegerPart: ",hesabu.getIntegerPart(4.5)); +andika("list: ",hesabu.list(1, 5, 1)); +fanya callback = unda(accumulator, currentValue){ + rudisha accumulator + currentValue; +} +andika("reduce: ",hesabu.reduce([1, 2, 3, 4],callback,0) );