1 /* 2 * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package test.java.lang.Math; 25 26 /* @test 27 @bug 8301226 28 @summary Add clamp() methods to java.lang.Math 29 */ 30 31 32 public class Clamp { main(String[] args)33 public static void main(String[] args) { 34 int failures = 0; 35 36 failures += testIntClamp(); 37 failures += testLongClamp(); 38 failures += testDoubleClamp(); 39 failures += testFloatClamp(); 40 41 if (failures > 0) { 42 System.err.println("Testing clamp incurred " + failures + " failures."); 43 throw new RuntimeException(); 44 } 45 } 46 testIntClamp()47 private static int testIntClamp() { 48 int failures = 0; 49 long[][] tests = { 50 // value, min, max, expected 51 {0, 1, 2, 1}, 52 {0, 0, 2, 0}, 53 {1, 0, 2, 1}, 54 {2, 0, 2, 2}, 55 {3, 0, 2, 2}, 56 {0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0}, 57 {Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE}, 58 {Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE}, 59 {Long.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE}, 60 {Long.MIN_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE}, 61 {0, 1, 1, 1}, 62 {Long.MAX_VALUE, 1, 1, 1} 63 }; 64 long[][] exceptionTests = { 65 // value, min, max 66 {1, 2, 0}, 67 {1, Integer.MAX_VALUE, Integer.MIN_VALUE} 68 }; 69 for (long[] test : tests) { 70 long value = test[0]; 71 int min = Math.toIntExact(test[1]); 72 int max = Math.toIntExact(test[2]); 73 int expected = Math.toIntExact(test[3]); 74 failures += checkEquals("(int) Math.clamp(" + value + ", " + min + ", " + max + ")", Math.clamp(value, min, max), expected); 75 failures += checkEquals("(int) StrictMath.clamp(" + value + ", " + min + ", " + max + ")", StrictMath.clamp(value, min, max), expected); 76 } 77 for (long[] test : exceptionTests) { 78 long value = test[0]; 79 int min = Math.toIntExact(test[1]); 80 int max = Math.toIntExact(test[2]); 81 failures += checkIllegalArgumentException("(int) Math.clamp(" + value + ", " + min + ", " + max + ")", 82 () -> Math.clamp(value, min, max)); 83 failures += checkIllegalArgumentException("(int) StrictMath.clamp(" + value + ", " + min + ", " + max + ")", 84 () -> StrictMath.clamp(value, min, max)); 85 } 86 return failures; 87 } 88 testLongClamp()89 private static int testLongClamp() { 90 int failures = 0; 91 long[][] tests = { 92 // value, min, max, expected 93 {0L, 1L, 2L, 1L}, 94 {0L, 0L, 2L, 0L}, 95 {1L, 0L, 2L, 1L}, 96 {2L, 0L, 2L, 2L}, 97 {3L, 0L, 2L, 2L}, 98 {0L, Long.MIN_VALUE, Long.MAX_VALUE, 0}, 99 {Long.MIN_VALUE, Long.MIN_VALUE, Long.MAX_VALUE, Long.MIN_VALUE}, 100 {Long.MAX_VALUE, Long.MIN_VALUE, Long.MAX_VALUE, Long.MAX_VALUE}, 101 {0, 1, 1, 1}, 102 {Long.MAX_VALUE, 1, 1, 1} 103 }; 104 long[][] exceptionTests = { 105 // value, min, max 106 {1L, 2L, 0L}, 107 {1, Long.MAX_VALUE, Long.MIN_VALUE} 108 }; 109 for (long[] test : tests) { 110 long value = test[0]; 111 long min = test[1]; 112 long max = test[2]; 113 long expected = test[3]; 114 failures += checkEquals("(long) Math.clamp(" + value + ", " + min + ", " + max + ")", Math.clamp(value, min, max), expected); 115 failures += checkEquals("(long) StrictMath.clamp(" + value + ", " + min + ", " + max + ")", StrictMath.clamp(value, min, max), expected); 116 } 117 for (long[] test : exceptionTests) { 118 long value = test[0]; 119 long min = test[1]; 120 long max = test[2]; 121 failures += checkIllegalArgumentException("(long) Math.clamp(" + value + ", " + min + ", " + max + ")", 122 () -> Math.clamp(value, min, max)); 123 failures += checkIllegalArgumentException("(long) StrictMath.clamp(" + value + ", " + min + ", " + max + ")", 124 () -> StrictMath.clamp(value, min, max)); 125 } 126 return failures; 127 } 128 testDoubleClamp()129 private static int testDoubleClamp() { 130 int failures = 0; 131 double[][] tests = { 132 // value, min, max, expected 133 {-0.1, 0.0, 0.5, 0.0}, 134 {-0.0, 0.0, 0.5, 0.0}, 135 {0.0, 0.0, 0.5, 0.0}, 136 {Double.MIN_VALUE, 0.0, 0.5, Double.MIN_VALUE}, 137 {0.2, 0.0, 0.5, 0.2}, 138 {Math.nextDown(0.5), 0.0, 0.5, Math.nextDown(0.5)}, 139 {0.5, 0.0, 0.5, 0.5}, 140 {Math.nextUp(0.5), 0.0, 0.5, 0.5}, 141 {0.6, 0.0, 0.5, 0.5}, 142 143 {Double.MAX_VALUE, 0.0, Double.POSITIVE_INFINITY, Double.MAX_VALUE}, 144 {Double.POSITIVE_INFINITY, 0.0, Double.MAX_VALUE, Double.MAX_VALUE}, 145 {-Double.MAX_VALUE, Double.NEGATIVE_INFINITY, 0.0, -Double.MAX_VALUE}, 146 {Double.NEGATIVE_INFINITY, -Double.MAX_VALUE, 0.0, -Double.MAX_VALUE}, 147 148 {-1.0, -0.0, 0.0, -0.0}, 149 {-0.0, -0.0, 0.0, -0.0}, 150 {0.0, -0.0, 0.0, 0.0}, 151 {1.0, -0.0, 0.0, 0.0}, 152 {-1.0, 0.0, 0.0, 0.0}, 153 {-0.0, 0.0, 0.0, 0.0}, 154 {0.0, 0.0, 0.0, 0.0}, 155 {1.0, 0.0, 0.0, 0.0}, 156 {-1.0, -0.0, -0.0, -0.0}, 157 {-0.0, -0.0, -0.0, -0.0}, 158 {0.0, -0.0, -0.0, -0.0}, 159 {1.0, -0.0, -0.0, -0.0}, 160 161 {Double.NaN, 0.0, 1.0, Double.NaN}, 162 {Double.NaN, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.NaN} 163 }; 164 double[][] exceptionTests = { 165 // value, min, max 166 {0.0, Double.NaN, Double.NaN}, 167 {0.0, 0.0, Double.NaN}, 168 {0.0, Double.NaN, 0.0}, 169 {Double.NaN, 1.0, 0.0}, 170 {0.0, 0.0, -0.0}, 171 {0.0, 1.0, -1.0} 172 }; 173 for (double[] test : tests) { 174 double value = test[0]; 175 double min = test[1]; 176 double max = test[2]; 177 double expected = test[3]; 178 failures += checkEquals("(double) Math.clamp(" + value + ", " + min + ", " + max + ")", Math.clamp(value, min, max), expected); 179 failures += checkEquals("(double) StrictMath.clamp(" + value + ", " + min + ", " + max + ")", StrictMath.clamp(value, min, max), expected); 180 } 181 for (double[] test : exceptionTests) { 182 double value = test[0]; 183 double min = test[1]; 184 double max = test[2]; 185 failures += checkIllegalArgumentException("(double) Math.clamp(" + value + ", " + min + ", " + max + ")", 186 () -> Math.clamp(value, min, max)); 187 failures += checkIllegalArgumentException("(double) StrictMath.clamp(" + value + ", " + min + ", " + max + ")", 188 () -> StrictMath.clamp(value, min, max)); 189 } 190 return failures; 191 } 192 testFloatClamp()193 private static int testFloatClamp() { 194 int failures = 0; 195 float[][] tests = { 196 // value, min, max, expected 197 {-0.1f, 0.0f, 0.5f, 0.0f}, 198 {-0.0f, 0.0f, 0.5f, 0.0f}, 199 {0.0f, 0.0f, 0.5f, 0.0f}, 200 {Float.MIN_VALUE, 0.0f, 0.5f, Float.MIN_VALUE}, 201 {0.2f, 0.0f, 0.5f, 0.2f}, 202 {Math.nextDown(0.5f), 0.0f, 0.5f, Math.nextDown(0.5f)}, 203 {0.5f, 0.0f, 0.5f, 0.5f}, 204 {Math.nextUp(0.5f), 0.0f, 0.5f, 0.5f}, 205 {0.6f, 0.0f, 0.5f, 0.5f}, 206 207 {Float.MAX_VALUE, 0.0f, Float.POSITIVE_INFINITY, Float.MAX_VALUE}, 208 {Float.POSITIVE_INFINITY, 0.0f, Float.MAX_VALUE, Float.MAX_VALUE}, 209 {-Float.MAX_VALUE, Float.NEGATIVE_INFINITY, 0.0f, -Float.MAX_VALUE}, 210 {Float.NEGATIVE_INFINITY, -Float.MAX_VALUE, 0.0f, -Float.MAX_VALUE}, 211 212 {-1.0f, -0.0f, 0.0f, -0.0f}, 213 {-0.0f, -0.0f, 0.0f, -0.0f}, 214 {0.0f, -0.0f, 0.0f, 0.0f}, 215 {1.0f, -0.0f, 0.0f, 0.0f}, 216 {-1.0f, 0.0f, 0.0f, 0.0f}, 217 {-0.0f, 0.0f, 0.0f, 0.0f}, 218 {0.0f, 0.0f, 0.0f, 0.0f}, 219 {1.0f, 0.0f, 0.0f, 0.0f}, 220 {-1.0f, -0.0f, -0.0f, -0.0f}, 221 {-0.0f, -0.0f, -0.0f, -0.0f}, 222 {0.0f, -0.0f, -0.0f, -0.0f}, 223 {1.0f, -0.0f, -0.0f, -0.0f}, 224 225 {Float.NaN, 0.0f, 1.0f, Float.NaN}, 226 {Float.NaN, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, Float.NaN} 227 }; 228 float[][] exceptionTests = { 229 // value, min, max 230 {0.0f, Float.NaN, Float.NaN}, 231 {0.0f, 0.0f, Float.NaN}, 232 {0.0f, Float.NaN, 0.0f}, 233 {Float.NaN, 1.0f, 0.0f}, 234 {0.0f, 0.0f, -0.0f}, 235 {0.0f, 1.0f, -1.0f} 236 }; 237 for (float[] test : tests) { 238 float value = test[0]; 239 float min = test[1]; 240 float max = test[2]; 241 float expected = test[3]; 242 failures += checkEquals("(float) Math.clamp(" + value + ", " + min + ", " + max + ")", Math.clamp(value, min, max), expected); 243 failures += checkEquals("(float) StrictMath.clamp(" + value + ", " + min + ", " + max + ")", StrictMath.clamp(value, min, max), expected); 244 } 245 for (float[] test : exceptionTests) { 246 float value = test[0]; 247 float min = test[1]; 248 float max = test[2]; 249 failures += checkIllegalArgumentException("(float) Math.clamp(" + value + ", " + min + ", " + max + ")", 250 () -> Math.clamp(value, min, max)); 251 failures += checkIllegalArgumentException("(float) StrictMath.clamp(" + value + ", " + min + ", " + max + ")", 252 () -> StrictMath.clamp(value, min, max)); 253 } 254 return failures; 255 } 256 checkIllegalArgumentException(String what, Runnable r)257 private static int checkIllegalArgumentException(String what, Runnable r) { 258 try { 259 r.run(); 260 } 261 catch (IllegalArgumentException ex) { 262 return 0; 263 } 264 System.err.println(what+": missing expected exception"); 265 return 1; 266 } 267 checkEquals(String what, double actual, double expected)268 private static int checkEquals(String what, double actual, double expected) { 269 if (Double.doubleToLongBits(actual) != Double.doubleToLongBits(expected)) { 270 System.err.println(what + ": expected = " + expected + "; actual = " + actual); 271 return 1; 272 } 273 return 0; 274 } 275 checkEquals(String what, long actual, long expected)276 private static int checkEquals(String what, long actual, long expected) { 277 if (actual != expected) { 278 System.err.println(what + ": expected = " + expected + "; actual = " + actual); 279 return 1; 280 } 281 return 0; 282 } 283 } 284