@Override
    public double membership(double x) {
        if (Double.isNaN(x)) {
            return Double.NaN;
        }
        //from Octave smf.m
        double a_b_ave = (bottomLeft + topLeft) / 2.0;
        double b_minus_a = topLeft - bottomLeft;
        double c_d_ave = (topRight + bottomRight) / 2.0;
        double d_minus_c = bottomRight - topRight;

        if (Op.isLE(x, bottomLeft)) {
            return 0.0;
        } else if (Op.isLE(x, a_b_ave)) {
            return 2.0 * Math.pow((x - bottomLeft) / b_minus_a, 2);
        } else if (Op.isLt(x, topLeft)) {
            return 1.0 - 2.0 * Math.pow((x - topLeft) / b_minus_a, 2);
        } else if (Op.isLE(x, topRight)) {
            return 1;
        } else if (Op.isLE(x, c_d_ave)) {
            return 1 - 2 * Math.pow((x - topRight) / d_minus_c, 2);
        } else if (Op.isLt(x, bottomRight)) {
            return 2 * Math.pow((x - bottomRight) / d_minus_c, 2);
        }

        return 0.0;
    }