001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.commons.svl.functions; 018 019import org.apache.juneau.commons.svl.*; 020 021/** 022 * Arithmetic functions for the {@code #{...}} script catalog. 023 * 024 * <p> 025 * All operations work on {@code double} so integer and decimal inputs compose naturally; the 026 * result renders as a String. Integer-perfect results omit the decimal point (e.g. 027 * {@code add(2, 3)} returns {@code "5"}, not {@code "5.0"}). 028 */ 029public final class ArithmeticFunctions { 030 031 private ArithmeticFunctions() {} 032 033 /** All function classes in this category. */ 034 @SuppressWarnings({ 035 "java:S2386", // ALL is an immutable compile-time registry; exposed as an array for the cross-package/varargs functions(...) API, so visibility cannot be reduced. 036 "unchecked" // Cast is safe: type verified by caller context. 037 }) 038 public static final Class<? extends VarFunction>[] ALL = new Class[] { 039 Add.class, Subtract.class, Multiply.class, Divide.class, Modulo.class, 040 Min.class, Max.class, Abs.class 041 }; 042 043 /** Render a double as a String, dropping the decimal portion when it's an exact integer. */ 044 static String render(double v) { 045 if (Double.isNaN(v) || Double.isInfinite(v)) return String.valueOf(v); 046 if (v == Math.floor(v) && Math.abs(v) < 1e18) 047 return String.valueOf((long) v); 048 return String.valueOf(v); 049 } 050 051 /** {@code #{add(a, b)}} — returns {@code a + b}. */ 052 public static class Add extends TypedFunction { 053 @Override public String name() { return "add"; } 054 public String invoke(double a, double b) { return render(a + b); } 055 } 056 057 /** {@code #{subtract(a, b)}} — returns {@code a - b}. */ 058 public static class Subtract extends TypedFunction { 059 @Override public String name() { return "subtract"; } 060 public String invoke(double a, double b) { return render(a - b); } 061 } 062 063 /** {@code #{multiply(a, b)}} — returns {@code a * b}. */ 064 public static class Multiply extends TypedFunction { 065 @Override public String name() { return "multiply"; } 066 public String invoke(double a, double b) { return render(a * b); } 067 } 068 069 /** {@code #{divide(a, b)}} — returns {@code a / b}. {@code b = 0} returns {@code Infinity} or {@code NaN} per IEEE 754. */ 070 public static class Divide extends TypedFunction { 071 @Override public String name() { return "divide"; } 072 public String invoke(double a, double b) { return render(a / b); } 073 } 074 075 /** {@code #{modulo(a, b)}} — returns {@code a % b}. */ 076 public static class Modulo extends TypedFunction { 077 @Override public String name() { return "modulo"; } 078 public String invoke(double a, double b) { return render(a % b); } 079 } 080 081 /** {@code #{min(a, b)}} — returns the smaller of two numbers. */ 082 public static class Min extends TypedFunction { 083 @Override public String name() { return "min"; } 084 public String invoke(double a, double b) { return render(Math.min(a, b)); } 085 } 086 087 /** {@code #{max(a, b)}} — returns the larger of two numbers. */ 088 public static class Max extends TypedFunction { 089 @Override public String name() { return "max"; } 090 public String invoke(double a, double b) { return render(Math.max(a, b)); } 091 } 092 093 /** {@code #{abs(a)}} — returns the absolute value of {@code a}. */ 094 public static class Abs extends TypedFunction { 095 @Override public String name() { return "abs"; } 096 public String invoke(double a) { return render(Math.abs(a)); } 097 } 098}