package com.tzld.piaoquan.ad.engine.commons.util;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;

public class NumUtil {

    public static double div(double d1, double d2) {
        if (d1 == 0 || d2 == 0) {
            return 0d;
        }
        return d1 / d2;
    }

    public static double divSmoothV1(double a, double b, double zscore) {
        // Wilson Smoothing
        if (a == 0 || b == 0) {
            return 0d;
        }
        double zscore2 = zscore * zscore;
        double p = a / b;
        double numerator = p + zscore2 / (2 * b) - zscore * Math.sqrt((p * (1 - p) + zscore2 / (4 * b)) / b);
        double denominator = 1 + zscore2 / b;
        return numerator / denominator;
    }

    public static double divSmoothV2(double a, double b, double beta) {
        if (a == 0 || b == 0) {
            return 0d;
        }
        return a / (b + beta);
    }

    public static double log(double a) {
        if (a <= 0) {
            return 0D;
        }
        return Math.log(a + 1.0);
    }

    public static double log10(double a) {
        if (a <= 0) {
            return 0d;
        }
        return Math.log10(a + 1.0);
    }

    public static double sigmoid(double x) {
        return 1 / (1 + Math.exp(-x));
    }

    public static double round(double value, int newScale){
        return new BigDecimal(value).setScale(newScale, RoundingMode.HALF_UP).doubleValue();
    }

    public static double[] softmax(double[] inputs) {
        double max = Arrays.stream(inputs).max().orElse(0);
        double[] expValues = Arrays.stream(inputs)
                .map(x -> Math.exp(x - max)) // Subtract max to stabilize
                .toArray();

        double sum = Arrays.stream(expValues).sum();

        return Arrays.stream(expValues)
                .map(x -> x / sum)
                .toArray();
    }

    @SafeVarargs
    public static <T extends Comparable<T>> T min(T... values) {
        if (values == null || values.length == 0) {
            throw new IllegalArgumentException("Values cannot be null or empty");
        }

        T minValue = values[0];
        for (T value : values) {
            if (value.compareTo(minValue) < 0) {
                minValue = value;
            }
        }

        return minValue;
    }

}
