001package conexp.fx.core.collections; 002 003/* 004 * #%L 005 * Concept Explorer FX 006 * %% 007 * Copyright (C) 2010 - 2023 Francesco Kriegel 008 * %% 009 * This program is free software: you can redistribute it and/or modify 010 * it under the terms of the GNU General Public License as 011 * published by the Free Software Foundation, either version 3 of the 012 * License, or (at your option) any later version. 013 * 014 * This program is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 017 * GNU General Public License for more details. 018 * 019 * You should have received a copy of the GNU General Public 020 * License along with this program. If not, see 021 * <http://www.gnu.org/licenses/gpl-3.0.html>. 022 * #L% 023 */ 024 025import java.util.Comparator; 026 027public class IntPair extends Pair<Integer, Integer> implements Cloneable { 028 029 public static final IntPair valueOf(final int x, final int y) { 030 return new IntPair(x, y); 031 } 032 033 public static final IntPair zero() { 034 return new IntPair(); 035 } 036 037 public static final Comparator<IntPair> CANTORIAN_COMPARATOR = new Comparator<IntPair>() { 038 039 @Override 040 public int compare(IntPair o1, IntPair o2) { 041 if (o1.equals(o2)) 042 return 0; 043 if (cantorianSum( 044 o1.x, 045 o1.y) < cantorianSum(o2.x, o2.y)) 046 return -1; 047 return 1; 048 } 049 }; 050 public static final Comparator<IntPair> POSITIVE_CANTORIAN_COMPARATOR = new Comparator<IntPair>() { 051 052 @Override 053 public int compare(IntPair o1, IntPair o2) { 054 if (o1.equals(o2)) 055 return 0; 056 if (positiveCantorianSum( 057 o1.x, 058 o1.y) < positiveCantorianSum( 059 o2.x, 060 o2.y)) 061 return -1; 062 return 1; 063 } 064 }; 065 066 public static final int cantorianSum(final int m, final int n) { 067 int shift = 0; 068 if (m < 0) 069 shift++; 070 if (n < 0) 071 shift += 2; 072 // shift is 0 iff both are positive 073 // shift is 1 iff only n is positive 074 // shift is 2 iff only m is positive 075 // shift is 3 iff none is positive 076 return 4 * positiveCantorianSum(Math.abs(m), Math.abs(n)) + shift; 077 } 078 079 /** 080 * cantorianSum is a bijection between positive integers and pairs of positive integers 081 */ 082 public static final int positiveCantorianSum(final int m, final int n) { 083 if (m < 0 || n < 0) 084 throw new RuntimeException("positive cantorian sum can only be calculated for positive integers!"); 085 return m + ((m + n + 1) * (m + n + 2)) / 2; 086// int cantorianSum = m; 087// for (int i = 1; i < m + n + 1; i++) 088// cantorianSum += i; 089// return cantorianSum; 090 } 091 092 public static final IntPair findPositiveCantorianSum(final int sum) { 093 int m = sum; 094 for (int n = 0; n < Integer.MAX_VALUE; n++) 095 if (positiveCantorianSum(m, n) == sum) 096 return IntPair.valueOf(m, n); 097 return null; 098 } 099 100 public IntPair(final int x, final int y) { 101 super(Integer.valueOf(x), Integer.valueOf(y)); 102 } 103 104 public IntPair() { 105 super(Integer.valueOf(0), Integer.valueOf(0)); 106 } 107 108 @Override 109 public boolean equals(Object object) { 110 if (object == null) 111 return false; 112 if (!(object instanceof IntPair)) 113 return false; 114 final IntPair other = (IntPair) object; 115 return other.x() == this.x() && other.y() == this.y(); 116 } 117 118 @Override 119 public int hashCode() { 120 return cantorianSum(x(), y()); 121 } 122 123// public final int x() { 124// return x.intValue(); 125// } 126// 127// public final int y() { 128// return y.intValue(); 129// } 130 131 @Override 132 public final IntPair clone() { 133 return new IntPair(x(), y()); 134 } 135 136 public final void setX(final int x) { 137 this.x = Integer.valueOf(x); 138 } 139 140 public final void setY(final int y) { 141 this.y = Integer.valueOf(y); 142 } 143 144 public final void set(final int x, final int y) { 145 setX(x); 146 setY(y); 147 } 148 149 public final void set(final IntPair coordinates) { 150 set(coordinates.x(), coordinates.y()); 151 } 152 153 public final IntPair negate() { 154 setX(-x()); 155 setY(-y()); 156 return this; 157 } 158 159 public final IntPair add(final int x, final int y) { 160 this.x += Integer.valueOf(x); 161 this.y += Integer.valueOf(y); 162 return this; 163 } 164 165 public final IntPair add(final IntPair coordinates) { 166 add(coordinates.x(), coordinates.y()); 167 return this; 168 } 169 170 public final IntPair subtract(final int x, final int y) { 171 this.x -= Integer.valueOf(x); 172 this.y -= Integer.valueOf(y); 173 return this; 174 } 175 176 public final IntPair subtract(final IntPair coordinates) { 177 subtract(coordinates.x(), coordinates.y()); 178 return this; 179 } 180 181 public final IntPair delta(final int x, final int y) { 182 return new IntPair(x, y).minus(this); 183 } 184 185 public final IntPair delta(final IntPair coordinates) { 186 return coordinates.clone().minus(this); 187 } 188 189 public final IntPair plus(final int x, final int y) { 190 return clone().add(x, y); 191 } 192 193 public final IntPair plus(final IntPair coordinates) { 194 return clone().add(coordinates); 195 } 196 197 public final IntPair minus(final int x, final int y) { 198 return clone().subtract(x, y); 199 } 200 201 public final IntPair minus(final IntPair coordinates) { 202 return clone().subtract(coordinates); 203 } 204 205 public final IntPair negative() { 206 return clone().negate(); 207 } 208}