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