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.lang; 018 019import static org.apache.juneau.commons.utils.AssertionUtils.*; 020 021/** 022 * A simple mutable float value. 023 * 024 * <p> 025 * This class extends {@link Value}<{@link Float}> and provides a convenient way to pass mutable 026 * float references to lambdas, inner classes, or methods. 027 * 028 * <h5 class='section'>Notes:</h5><ul> 029 * <li class='note'> 030 * This class is <b>not thread-safe</b>. 031 * </ul> 032 * 033 * <h5 class='section'>Example:</h5> 034 * <p class='bjava'> 035 * <jc>// Create a float value to track a running sum</jc> 036 * FloatValue <jv>sum</jv> = FloatValue.<jsm>create</jsm>(); 037 * 038 * <jc>// Use in a lambda to accumulate values</jc> 039 * list.forEach(<jv>x</jv> -> { 040 * <jv>sum</jv>.set(<jv>sum</jv>.get() + <jv>x</jv>.floatValue()); 041 * }); 042 * 043 * <jsm>log</jsm>(<js>"Total: "</js> + <jv>sum</jv>.get()); 044 * </p> 045 * 046 * <h5 class='section'>See Also:</h5><ul> 047 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauCommonsLang">Lang Package</a> 048 * </ul> 049 */ 050public class FloatValue extends Value<Float> { 051 052 /** 053 * Creates a new float value initialized to <c>0.0f</c>. 054 * 055 * <h5 class='section'>Example:</h5> 056 * <p class='bjava'> 057 * FloatValue <jv>value</jv> = FloatValue.<jsm>create</jsm>(); 058 * <jsm>assertEquals</jsm>(0.0f, <jv>value</jv>.get()); 059 * </p> 060 * 061 * @return A new float value. 062 */ 063 public static FloatValue create() { 064 return of(0.0f); 065 } 066 067 /** 068 * Creates a new float value with the specified initial value. 069 * 070 * <h5 class='section'>Example:</h5> 071 * <p class='bjava'> 072 * FloatValue <jv>value</jv> = FloatValue.<jsm>of</jsm>(3.14f); 073 * <jsm>assertEquals</jsm>(3.14f, <jv>value</jv>.get()); 074 * </p> 075 * 076 * @param value The initial value. 077 * @return A new float value. 078 */ 079 public static FloatValue of(Float value) { 080 return new FloatValue(value); 081 } 082 083 /** 084 * Constructor. 085 * 086 * @param value The initial value. 087 */ 088 public FloatValue(Float value) { 089 super(value); 090 } 091 092 /** 093 * Checks if the current value equals the specified value within the given precision. 094 * 095 * <p> 096 * This method handles <jk>null</jk> values safely and performs precision-based equality comparison 097 * using absolute difference. The comparison returns <jk>true</jk> if the absolute difference between 098 * the two values is less than or equal to the specified precision. 099 * 100 * <h5 class='section'>Example:</h5> 101 * <p class='bjava'> 102 * FloatValue <jv>value</jv> = FloatValue.<jsm>of</jsm>(3.14f); 103 * <jsm>assertTrue</jsm>(<jv>value</jv>.is(3.14f, 0.01f)); <jc>// Exact match within 0.01</jc> 104 * <jsm>assertTrue</jsm>(<jv>value</jv>.is(3.15f, 0.02f)); <jc>// Within 0.02</jc> 105 * <jsm>assertFalse</jsm>(<jv>value</jv>.is(3.15f, 0.001f)); <jc>// Not within 0.001</jc> 106 * 107 * <jc>// Handles null values</jc> 108 * FloatValue <jv>empty</jv> = FloatValue.<jsm>create</jsm>(); 109 * <jv>empty</jv>.set(<jk>null</jk>); 110 * <jsm>assertFalse</jsm>(<jv>empty</jv>.is(3.14f, 0.01f)); <jc>// Null doesn't match any value</jc> 111 * 112 * <jc>// Precision-based comparison</jc> 113 * FloatValue <jv>pi</jv> = FloatValue.<jsm>of</jsm>(3.14159f); 114 * <jsm>assertTrue</jsm>(<jv>pi</jv>.is(3.14f, 0.002f)); <jc>// Within 0.002 precision</jc> 115 * </p> 116 * 117 * @param other The value to compare with. 118 * @param precision The maximum allowed difference for equality. Must be non-negative. 119 * @return <jk>true</jk> if the absolute difference between the values is less than or equal to precision. 120 * @throws IllegalArgumentException if precision is negative. 121 */ 122 public boolean is(float other, float precision) { 123 assertArg(precision >= 0, "Precision must be non-negative"); 124 var v = get(); 125 if (v == null) { 126 return false; 127 } 128 return Math.abs(v - other) <= precision; 129 } 130 131 /** 132 * Checks if the current value matches any of the specified values within the given precision. 133 * 134 * <p> 135 * This method handles <jk>null</jk> values safely and performs precision-based equality comparison 136 * for each value using absolute difference. 137 * 138 * <h5 class='section'>Example:</h5> 139 * <p class='bjava'> 140 * FloatValue <jv>value</jv> = FloatValue.<jsm>of</jsm>(3.14f); 141 * <jsm>assertTrue</jsm>(<jv>value</jv>.isAny(0.01f, 2.5f, 3.15f, 5.0f)); <jc>// Matches 3.15f within 0.01</jc> 142 * <jsm>assertFalse</jsm>(<jv>value</jv>.isAny(0.001f, 1.0f, 2.0f, 5.0f)); <jc>// No match within 0.001</jc> 143 * 144 * <jc>// Empty array returns false</jc> 145 * <jsm>assertFalse</jsm>(<jv>value</jv>.isAny(0.01f)); 146 * </p> 147 * 148 * @param precision The maximum allowed difference for equality. Must be non-negative and is the first parameter. 149 * @param values The values to compare to. 150 * @return <jk>true</jk> if the current value matches any of the specified values within the precision. 151 * @throws IllegalArgumentException if precision is negative. 152 */ 153 public boolean isAny(float precision, float...values) { 154 assertArg(precision >= 0, "Precision must be non-negative"); 155 assertArgNotNull("values", values); 156 var v = get(); 157 if (v == null) 158 return false; 159 for (var value : values) 160 if (Math.abs(v - value) <= precision) 161 return true; 162 return false; 163 } 164}