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.commons.functor.range; 018 019import java.util.Iterator; 020 021import org.apache.commons.functor.BinaryFunction; 022import org.apache.commons.lang3.Validate; 023 024/** 025 * A generator for a range of float. 026 * 027 * @since 1.0 028 * @version $Revision$ $Date$ 029 */ 030public class FloatRange extends NumericRange<Float> { 031 032 // attributes 033 // --------------------------------------------------------------- 034 035 /** 036 * Calculate default step. 037 */ 038 public static final BinaryFunction<Float, Float, Float> DEFAULT_STEP = new BinaryFunction<Float, Float, Float>() { 039 040 public Float evaluate(Float left, Float right) { 041 return left > right ? -1.0f : 1.0f; 042 } 043 }; 044 045 // constructors 046 // --------------------------------------------------------------- 047 /** 048 * Create a new FloatRange. 049 * 050 * @param from start 051 * @param to end 052 */ 053 public FloatRange(Number from, Number to) { 054 this(from.floatValue(), to.floatValue()); 055 } 056 057 /** 058 * Create a new FloatRange. 059 * 060 * @param from start 061 * @param to end 062 * @param step increment 063 */ 064 public FloatRange(Number from, Number to, Number step) { 065 this(from.floatValue(), to.floatValue(), step.floatValue()); 066 } 067 068 /** 069 * Create a new FloatRange. 070 * 071 * @param from start 072 * @param to end 073 */ 074 public FloatRange(float from, float to) { 075 this(from, to, DEFAULT_STEP.evaluate(from, to).floatValue()); 076 } 077 078 /** 079 * Create a new FloatRange. 080 * 081 * @param from start 082 * @param to end 083 * @param step increment 084 */ 085 public FloatRange(float from, float to, float step) { 086 this(from, DEFAULT_LEFT_BOUND_TYPE, to, DEFAULT_RIGHT_BOUND_TYPE, step); 087 } 088 089 /** 090 * Create a new FloatRange. 091 * 092 * @param from start 093 * @param to end 094 * @throws NullPointerException if either {@link Endpoint} is {@code null} 095 */ 096 public FloatRange(Endpoint<Float> from, Endpoint<Float> to) { 097 this(from, to, DEFAULT_STEP.evaluate(from.getValue(), to.getValue())); 098 } 099 100 /** 101 * Create a new FloatRange. 102 * 103 * @param from start 104 * @param to end 105 * @param step increment 106 * @throws NullPointerException if either {@link Endpoint} is {@code null} 107 */ 108 public FloatRange(Endpoint<Float> from, Endpoint<Float> to, float step) { 109 super(from, to, Float.valueOf(step), new BinaryFunction<Float, Float, Float>() { 110 111 public Float evaluate(Float left, Float right) { 112 return Float.valueOf(left.floatValue() + right.floatValue()); 113 } 114 }); 115 final float f = from.getValue(); 116 final float t = to.getValue(); 117 118 Validate.isTrue(f == t || Math.signum(step) == Math.signum(t - f), 119 "Will never reach '%s' from '%s' using step %s", t, f, step); 120 } 121 122 /** 123 * Create a new FloatRange. 124 * 125 * @param from start 126 * @param leftBoundType type of left bound 127 * @param to end 128 * @param rightBoundType type of right bound 129 * @throws NullPointerException if either bound type is {@code null} 130 */ 131 public FloatRange(float from, BoundType leftBoundType, float to, 132 BoundType rightBoundType) { 133 this(from, leftBoundType, to, rightBoundType, DEFAULT_STEP.evaluate(from, to)); 134 } 135 136 /** 137 * Create a new FloatRange. 138 * 139 * @param from start 140 * @param leftBoundType type of left bound 141 * @param to end 142 * @param rightBoundType type of right bound 143 * @param step increment 144 * @throws NullPointerException if either bound type is {@code null} 145 */ 146 public FloatRange(float from, BoundType leftBoundType, float to, 147 BoundType rightBoundType, float step) { 148 this(new Endpoint<Float>(from, leftBoundType), new Endpoint<Float>(to, rightBoundType), step); 149 } 150 151 /** 152 * {@inheritDoc} 153 */ 154 protected Iterator<Float> createIterator() { 155 return new Iterator<Float>() { 156 private float currentValue; 157 158 { 159 currentValue = leftEndpoint.getValue(); 160 161 if (leftEndpoint.getBoundType() == BoundType.OPEN) { 162 this.currentValue += step; 163 } 164 } 165 166 public void remove() { 167 throw new UnsupportedOperationException(); 168 } 169 170 public Float next() { 171 final float step = getStep(); 172 final float r = currentValue; 173 currentValue += step; 174 return Float.valueOf(r); 175 } 176 177 public boolean hasNext() { 178 final int cmp = Float.compare(currentValue, rightEndpoint.getValue()); 179 180 if (cmp == 0) { 181 return rightEndpoint.getBoundType() == BoundType.CLOSED; 182 } 183 if (step > 0f) { 184 return cmp < 0; 185 } 186 return cmp > 0; 187 } 188 }; 189 } 190 191}