This commit is contained in:
Gatecraft 2016-07-14 23:08:50 +02:00
parent 1e91428ce6
commit 7ad342b85c
39 changed files with 4405 additions and 0 deletions

BIN
res/font_big.ttf Normal file

Binary file not shown.

BIN
res/font_small.ttf Normal file

Binary file not shown.

BIN
res/skin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
res/skin.xcf Normal file

Binary file not shown.

View File

@ -0,0 +1,613 @@
package com.rits.cloning;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.net.URL;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
/**
* Cloner: deep clone objects.
*
* This class is thread safe. One instance can be used by multiple threads on the same time.
*
* @author kostantinos.kougios
* 18 Sep 2008
*/
public class Cloner {
private final IInstantiationStrategy instantiationStrategy;
private final Set<Class<?>> ignored = new HashSet<Class<?>>();
private final Set<Class<?>> ignoredInstanceOf = new HashSet<Class<?>>();
private final Set<Class<?>> nullInstead = new HashSet<Class<?>>();
private final Map<Class<?>, IFastCloner> fastCloners = new HashMap<Class<?>, IFastCloner>();
private final Map<Object, Boolean> ignoredInstances = new IdentityHashMap<Object, Boolean>();
private final ConcurrentHashMap<Class<?>, List<Field>> fieldsCache = new ConcurrentHashMap<Class<?>, List<Field>>();
public IDumpCloned getDumpCloned() {
return dumpCloned;
}
/**
* provide a cloned classes dumper (so i.e. they can be logged or stored in a file
* instead of the default behaviour which is to println(cloned) )
*
* @param dumpCloned an implementation of the interface which can dump the
* cloned classes.
*/
public void setDumpCloned(IDumpCloned dumpCloned) {
this.dumpCloned = dumpCloned;
}
private IDumpCloned dumpCloned = null;
private boolean cloningEnabled = true;
private boolean nullTransient = false;
private boolean cloneSynthetics = true;
public Cloner() {
this.instantiationStrategy = ObjenesisInstantiationStrategy.getInstance();
init();
}
public Cloner(final IInstantiationStrategy instantiationStrategy) {
this.instantiationStrategy = instantiationStrategy;
init();
}
public boolean isNullTransient() {
return nullTransient;
}
/**
* this makes the cloner to set a transient field to null upon cloning.
*
* NOTE: primitive types can't be nulled. Their value will be set to default, i.e. 0 for int
*
* @param nullTransient true for transient fields to be nulled
*/
public void setNullTransient(final boolean nullTransient) {
this.nullTransient = nullTransient;
}
public void setCloneSynthetics(final boolean cloneSynthetics) {
this.cloneSynthetics = cloneSynthetics;
}
private void init() {
registerKnownJdkImmutableClasses();
registerKnownConstants();
registerFastCloners();
}
/**
* registers a std set of fast cloners.
*/
protected void registerFastCloners() {
fastCloners.put(GregorianCalendar.class, new FastClonerCalendar());
fastCloners.put(ArrayList.class, new FastClonerArrayList());
fastCloners.put(LinkedList.class, new FastClonerLinkedList());
fastCloners.put(HashSet.class, new FastClonerHashSet());
fastCloners.put(HashMap.class, new FastClonerHashMap());
fastCloners.put(TreeMap.class, new FastClonerTreeMap());
fastCloners.put(ConcurrentHashMap.class, new FastClonerConcurrentHashMap());
}
private IDeepCloner deepCloner = new IDeepCloner() {
public <T> T deepClone(T o, Map<Object, Object> clones) {
try {
return cloneInternal(o, clones);
} catch (IllegalAccessException e) {
// just rethrow unchecked
throw new IllegalStateException(e);
}
}
};
protected Object fastClone(final Object o, final Map<Object, Object> clones) throws IllegalAccessException {
final Class<? extends Object> c = o.getClass();
final IFastCloner fastCloner = fastCloners.get(c);
if (fastCloner != null) return fastCloner.clone(o, deepCloner, clones);
return null;
}
public void registerConstant(final Object o) {
ignoredInstances.put(o, true);
}
public void registerConstant(final Class<?> c, final String privateFieldName) {
try {
final Field field = c.getDeclaredField(privateFieldName);
field.setAccessible(true);
final Object v = field.get(null);
ignoredInstances.put(v, true);
} catch (final SecurityException e) {
throw new RuntimeException(e);
} catch (final NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (final IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (final IllegalAccessException e) {
throw new RuntimeException(e);
}
}
/**
* registers some known JDK immutable classes. Override this to register your
* own list of jdk's immutable classes
*/
protected void registerKnownJdkImmutableClasses() {
registerImmutable(String.class);
registerImmutable(Integer.class);
registerImmutable(Long.class);
registerImmutable(Boolean.class);
registerImmutable(Class.class);
registerImmutable(Float.class);
registerImmutable(Double.class);
registerImmutable(Character.class);
registerImmutable(Byte.class);
registerImmutable(Short.class);
registerImmutable(Void.class);
registerImmutable(BigDecimal.class);
registerImmutable(BigInteger.class);
registerImmutable(URI.class);
registerImmutable(URL.class);
registerImmutable(UUID.class);
registerImmutable(Pattern.class);
}
protected void registerKnownConstants() {
// registering known constants of the jdk.
registerStaticFields(TreeSet.class, HashSet.class, HashMap.class, TreeMap.class);
}
/**
* registers all static fields of these classes. Those static fields won't be cloned when an instance
* of the class is cloned.
*
* This is useful i.e. when a static field object is added into maps or sets. At that point, there is no
* way for the cloner to know that it was static except if it is registered.
*
* @param classes array of classes
*/
public void registerStaticFields(final Class<?>... classes) {
for (final Class<?> c : classes) {
final List<Field> fields = allFields(c);
for (final Field field : fields) {
final int mods = field.getModifiers();
if (Modifier.isStatic(mods) && !field.getType().isPrimitive()) {
registerConstant(c, field.getName());
}
}
}
}
/**
* spring framework friendly version of registerStaticFields
*
* @param set a set of classes which will be scanned for static fields
*/
public void setExtraStaticFields(final Set<Class<?>> set) {
registerStaticFields((Class<?>[]) set.toArray());
}
/**
* instances of classes that shouldn't be cloned can be registered using this method.
*
* @param c The class that shouldn't be cloned. That is, whenever a deep clone for
* an object is created and c is encountered, the object instance of c will
* be added to the clone.
*/
public void dontClone(final Class<?>... c) {
for (final Class<?> cl : c) {
ignored.add(cl);
}
}
public void dontCloneInstanceOf(final Class<?>... c) {
for (final Class<?> cl : c) {
ignoredInstanceOf.add(cl);
}
}
public void setDontCloneInstanceOf(final Class<?>... c) {
dontCloneInstanceOf(c);
}
/**
* instead of cloning these classes will set the field to null
*
* @param c the classes to nullify during cloning
*/
public void nullInsteadOfClone(final Class<?>... c) {
for (final Class<?> cl : c) {
nullInstead.add(cl);
}
}
// spring framework friendly version of nullInsteadOfClone
public void setExtraNullInsteadOfClone(final Set<Class<?>> set) {
nullInstead.addAll(set);
}
/**
* registers an immutable class. Immutable classes are not cloned.
*
* @param c the immutable class
*/
public void registerImmutable(final Class<?>... c) {
for (final Class<?> cl : c) {
ignored.add(cl);
}
}
// spring framework friendly version of registerImmutable
public void setExtraImmutables(final Set<Class<?>> set) {
ignored.addAll(set);
}
public void registerFastCloner(final Class<?> c, final IFastCloner fastCloner) {
if (fastCloners.containsKey(c)) throw new IllegalArgumentException(c + " already fast-cloned!");
fastCloners.put(c, fastCloner);
}
public void unregisterFastCloner(final Class<?> c) {
fastCloners.remove(c);
}
/**
* creates a new instance of c. Override to provide your own implementation
*
* @param <T> the type of c
* @param c the class
* @return a new instance of c
*/
protected <T> T newInstance(final Class<T> c) {
return instantiationStrategy.newInstance(c);
}
@SuppressWarnings("unchecked")
public <T> T fastCloneOrNewInstance(final Class<T> c) {
try {
final T fastClone = (T) fastClone(c, null);
if (fastClone != null) return fastClone;
} catch (final IllegalAccessException e) {
throw new RuntimeException(e);
}
return newInstance(c);
}
/**
* deep clones "o".
*
* @param <T> the type of "o"
* @param o the object to be deep-cloned
* @return a deep-clone of "o".
*/
public <T> T deepClone(final T o) {
if (o == null) return null;
if (!cloningEnabled) return o;
if (dumpCloned != null) {
dumpCloned.startCloning(o.getClass());
}
final Map<Object, Object> clones = new IdentityHashMap<Object, Object>(16);
try {
return cloneInternal(o, clones);
} catch (final IllegalAccessException e) {
throw new CloningException("error during cloning of " + o, e);
}
}
public <T> T deepCloneDontCloneInstances(final T o, final Object... dontCloneThese) {
if (o == null) return null;
if (!cloningEnabled) return o;
if (dumpCloned != null) {
dumpCloned.startCloning(o.getClass());
}
final Map<Object, Object> clones = new IdentityHashMap<Object, Object>(16);
for (final Object dc : dontCloneThese) {
clones.put(dc, dc);
}
try {
return cloneInternal(o, clones);
} catch (final IllegalAccessException e) {
throw new CloningException("error during cloning of " + o, e);
}
}
/**
* shallow clones "o". This means that if c=shallowClone(o) then
* c!=o. Any change to c won't affect o.
*
* @param <T> the type of o
* @param o the object to be shallow-cloned
* @return a shallow clone of "o"
*/
public <T> T shallowClone(final T o) {
if (o == null) return null;
if (!cloningEnabled) return o;
try {
return cloneInternal(o, null);
} catch (final IllegalAccessException e) {
throw new CloningException("error during cloning of " + o, e);
}
}
// caches immutables for quick reference
private final ConcurrentHashMap<Class<?>, Boolean> immutables = new ConcurrentHashMap<Class<?>, Boolean>();
private boolean cloneAnonymousParent = true;
/**
* override this to decide if a class is immutable. Immutable classes are not cloned.
*
* @param clz the class under check
* @return true to mark clz as immutable and skip cloning it
*/
protected boolean considerImmutable(final Class<?> clz) {
return false;
}
protected Class<?> getImmutableAnnotation() {
return Immutable.class;
}
/**
* decides if a class is to be considered immutable or not
*
* @param clz the class under check
* @return true if the clz is considered immutable
*/
private boolean isImmutable(final Class<?> clz) {
final Boolean isIm = immutables.get(clz);
if (isIm != null) return isIm;
if (considerImmutable(clz)) return true;
final Class<?> immutableAnnotation = getImmutableAnnotation();
for (final Annotation annotation : clz.getDeclaredAnnotations()) {
if (annotation.annotationType() == immutableAnnotation) {
immutables.put(clz, Boolean.TRUE);
return true;
}
}
Class<?> c = clz.getSuperclass();
while (c != null && c != Object.class) {
for (final Annotation annotation : c.getDeclaredAnnotations()) {
if (annotation.annotationType() == Immutable.class) {
final Immutable im = (Immutable) annotation;
if (im.subClass()) {
immutables.put(clz, Boolean.TRUE);
return true;
}
}
}
c = c.getSuperclass();
}
immutables.put(clz, Boolean.FALSE);
return false;
}
@SuppressWarnings("unchecked")
protected <T> T cloneInternal(final T o, final Map<Object, Object> clones) throws IllegalAccessException {
if (o == null) return null;
if (o == this) return null; // don't clone the cloner!
if (ignoredInstances.containsKey(o)) return o;
if (o instanceof Enum) return o;
final Class<T> clz = (Class<T>) o.getClass();
// skip cloning ignored classes
if (nullInstead.contains(clz)) return null;
if (ignored.contains(clz)) return o;
for (final Class<?> iClz : ignoredInstanceOf) {
if (iClz.isAssignableFrom(clz)) return o;
}
if (isImmutable(clz)) return o;
if (o instanceof IFreezable) {
final IFreezable f = (IFreezable) o;
if (f.isFrozen()) return o;
}
final Object clonedPreviously = clones != null ? clones.get(o) : null;
if (clonedPreviously != null) return (T) clonedPreviously;
final Object fastClone = fastClone(o, clones);
if (fastClone != null) {
if (clones != null) {
clones.put(o, fastClone);
}
return (T) fastClone;
}
if (dumpCloned != null) {
dumpCloned.startCloning(o.getClass());
}
if (clz.isArray()) {
return cloneArray(o, clones);
}
return cloneObject(o, clones, clz);
}
// clones o, no questions asked!
private <T> T cloneObject(T o, Map<Object, Object> clones, Class<T> clz) throws IllegalAccessException {
final T newInstance = newInstance(clz);
if (clones != null) {
clones.put(o, newInstance);
}
final List<Field> fields = allFields(clz);
for (final Field field : fields) {
final int modifiers = field.getModifiers();
if (!Modifier.isStatic(modifiers)) {
if ( ! (nullTransient && Modifier.isTransient(modifiers)) ) {
// request by Jonathan : transient fields can be null-ed
final Object fieldObject = field.get(o);
final boolean shouldClone = (cloneSynthetics || !field.isSynthetic()) && (cloneAnonymousParent || !isAnonymousParent(field));
final Object fieldObjectClone = clones != null ? (shouldClone ? cloneInternal(fieldObject, clones) : fieldObject) : fieldObject;
field.set(newInstance, fieldObjectClone);
if (dumpCloned != null && fieldObjectClone != fieldObject) {
dumpCloned.cloning(field, o.getClass());
}
}
}
}
return newInstance;
}
@SuppressWarnings("unchecked")
private <T> T cloneArray(T o, Map<Object, Object> clones) throws IllegalAccessException {
final Class<T> clz = (Class<T>) o.getClass();
final int length = Array.getLength(o);
final T newInstance = (T) Array.newInstance(clz.getComponentType(), length);
if (clones != null) {
clones.put(o, newInstance);
}
if(clz.getComponentType().isPrimitive() || isImmutable(clz.getComponentType())) {
System.arraycopy(o, 0, newInstance, 0, length);
} else {
for (int i = 0; i < length; i++) {
final Object v = Array.get(o, i);
final Object clone = clones != null ? cloneInternal(v, clones) : v;
Array.set(newInstance, i, clone);
}
}
return newInstance;
}
private boolean isAnonymousParent(final Field field) {
return "this$0".equals(field.getName());
}
/**
* copies all properties from src to dest. Src and dest can be of different class, provided they contain same field names/types
*
* @param src the source object
* @param dest the destination object which must contain as minimum all the fields of src
*/
public <T, E extends T> void copyPropertiesOfInheritedClass(final T src, final E dest) {
if (src == null) throw new IllegalArgumentException("src can't be null");
if (dest == null) throw new IllegalArgumentException("dest can't be null");
final Class<? extends Object> srcClz = src.getClass();
final Class<? extends Object> destClz = dest.getClass();
if (srcClz.isArray()) {
if (!destClz.isArray())
throw new IllegalArgumentException("can't copy from array to non-array class " + destClz);
final int length = Array.getLength(src);
for (int i = 0; i < length; i++) {
final Object v = Array.get(src, i);
Array.set(dest, i, v);
}
return;
}
final List<Field> fields = allFields(srcClz);
final List<Field> destFields = allFields(dest.getClass());
for (final Field field : fields) {
if (!Modifier.isStatic(field.getModifiers())) {
try {
final Object fieldObject = field.get(src);
field.setAccessible(true);
if (destFields.contains(field)) {
field.set(dest, fieldObject);
}
} catch (final IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (final IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}
/**
* reflection utils
*/
private void addAll(final List<Field> l, final Field[] fields) {
for (final Field field : fields) {
if (!field.isAccessible()) {
field.setAccessible(true);
}
l.add(field);
}
}
/**
* reflection utils, override this to choose which fields to clone
*/
protected List<Field> allFields(final Class<?> c) {
List<Field> l = fieldsCache.get(c);
if (l == null) {
l = new LinkedList<Field>();
final Field[] fields = c.getDeclaredFields();
addAll(l, fields);
Class<?> sc = c;
while ((sc = sc.getSuperclass()) != Object.class && sc != null) {
addAll(l, sc.getDeclaredFields());
}
fieldsCache.putIfAbsent(c, l);
}
return l;
}
public boolean isDumpClonedClasses() {
return dumpCloned != null;
}
/**
* will println() all cloned classes. Useful for debugging only. Use
* setDumpCloned() if you want to control where to print the cloned
* classes.
*
* @param dumpClonedClasses true to enable printing all cloned classes
*/
public void setDumpClonedClasses(final boolean dumpClonedClasses) {
if (dumpClonedClasses) {
dumpCloned = new IDumpCloned() {
public void startCloning(Class<?> clz) {
System.out.println("clone>" + clz);
}
public void cloning(Field field, Class<?> clz) {
System.out.println("cloned field>" + field + " -- of class " + clz);
}
};
} else dumpCloned = null;
}
public boolean isCloningEnabled() {
return cloningEnabled;
}
public void setCloningEnabled(final boolean cloningEnabled) {
this.cloningEnabled = cloningEnabled;
}
/**
* if false, anonymous classes parent class won't be cloned. Default is true
*/
public void setCloneAnonymousParent(final boolean cloneAnonymousParent) {
this.cloneAnonymousParent = cloneAnonymousParent;
}
public boolean isCloneAnonymousParent() {
return cloneAnonymousParent;
}
/**
* @return a standard cloner instance, will do for most use cases
*/
public static Cloner standard() {
return new Cloner();
}
/**
* @return if Cloner lib is in a shared jar folder for a container (i.e. tomcat/shared), then
* this method is preferable in order to instantiate cloner. Please
* see https://code.google.com/p/cloning/issues/detail?id=23
*/
public static Cloner shared() {
return new Cloner(new ObjenesisInstantiationStrategy());
}
}

View File

@ -0,0 +1,20 @@
package com.rits.cloning;
/**
* thrown if cloning fails
*
* @author kostantinos.kougios
*
* 18 Jan 2009
*/
public class CloningException extends RuntimeException
{
private static final long serialVersionUID = 3815175312001146867L;
public CloningException(final String message, final Throwable cause)
{
super(message, cause);
}
}

View File

@ -0,0 +1,25 @@
package com.rits.cloning;
import java.util.ArrayList;
import java.util.Map;
/**
* @author kostantinos.kougios
*
* 21 May 2009
*/
public class FastClonerArrayList implements IFastCloner
{
@SuppressWarnings({ "unchecked", "rawtypes" })
public Object clone(final Object t, final IDeepCloner cloner, final Map<Object, Object> clones) {
final ArrayList al = (ArrayList) t;
final ArrayList l = new ArrayList(al.size());
for (final Object o : al)
{
final Object cloneInternal = cloner.deepClone(o, clones);
l.add(cloneInternal);
}
return l;
}
}

View File

@ -0,0 +1,22 @@
package com.rits.cloning;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Map;
import java.util.TimeZone;
/**
* @author kostantinos.kougios
*
* 21 May 2009
*/
public class FastClonerCalendar implements IFastCloner
{
public Object clone(final Object t, final IDeepCloner cloner, final Map<Object, Object> clones) {
final GregorianCalendar gc = new GregorianCalendar();
Calendar c = (Calendar) t;
gc.setTimeInMillis(c.getTimeInMillis());
gc.setTimeZone((TimeZone) c.getTimeZone().clone());
return gc;
}
}

View File

@ -0,0 +1,26 @@
package com.rits.cloning;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author kostantinos.kougios
*
* 18 Oct 2011
*/
public class FastClonerConcurrentHashMap implements IFastCloner
{
@SuppressWarnings({ "unchecked", "rawtypes" })
public Object clone(final Object t, final IDeepCloner cloner, final Map<Object, Object> clones) {
final ConcurrentHashMap<Object, Object> m = (ConcurrentHashMap) t;
final ConcurrentHashMap result = new ConcurrentHashMap();
for (final Map.Entry e : m.entrySet())
{
final Object key = cloner.deepClone(e.getKey(), clones);
final Object value = cloner.deepClone(e.getValue(), clones);
result.put(key, value);
}
return result;
}
}

View File

@ -0,0 +1,26 @@
package com.rits.cloning;
import java.util.Collection;
import java.util.Map;
/**
* @author kostantinos.kougios
*
* 21 May 2009
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public abstract class FastClonerCustomCollection<T extends Collection> implements IFastCloner
{
public abstract T getInstance(T o);
public Object clone(final Object t, final IDeepCloner cloner, final Map<Object, Object> clones) {
final T c = getInstance((T) t);
final T l = (T) t;
for (final Object o : l)
{
final Object clone = cloner.deepClone(o, clones);
c.add(clone);
}
return c;
}
}

View File

@ -0,0 +1,28 @@
package com.rits.cloning;
import java.util.Map;
import java.util.Set;
/**
* @author kostantinos.kougios
*
* 21 May 2009
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public abstract class FastClonerCustomMap<T extends Map> implements IFastCloner
{
public Object clone(final Object t, final IDeepCloner cloner, final Map<Object, Object> clones) {
final T m = (T) t;
final T result = getInstance((T) t);
final Set<Map.Entry<Object, Object>> entrySet = m.entrySet();
for (final Map.Entry e : entrySet)
{
final Object key = cloner.deepClone(e.getKey(), clones);
final Object value = cloner.deepClone(e.getValue(), clones);
result.put(key, value);
}
return result;
}
protected abstract T getInstance(T t);
}

View File

@ -0,0 +1,26 @@
package com.rits.cloning;
import java.util.HashMap;
import java.util.Map;
/**
* @author kostantinos.kougios
*
* 21 May 2009
*/
public class FastClonerHashMap implements IFastCloner
{
@SuppressWarnings({ "unchecked", "rawtypes" })
public Object clone(final Object t, final IDeepCloner cloner, final Map<Object, Object> clones) {
final HashMap<Object, Object> m = (HashMap) t;
final HashMap result = new HashMap();
for (final Map.Entry e : m.entrySet())
{
final Object key = cloner.deepClone(e.getKey(), clones);
final Object value = cloner.deepClone(e.getValue(), clones);
result.put(key, value);
}
return result;
}
}

View File

@ -0,0 +1,24 @@
package com.rits.cloning;
import java.util.HashSet;
import java.util.Map;
/**
* @author kostantinos.kougios
*
* 21 May 2009
*/
public class FastClonerHashSet implements IFastCloner
{
@SuppressWarnings({ "unchecked", "rawtypes" })
public Object clone(final Object t, final IDeepCloner cloner, final Map<Object, Object> clones) {
final HashSet al = (HashSet) t;
final HashSet l = new HashSet();
for (final Object o : al)
{
final Object cloneInternal = cloner.deepClone(o, clones);
l.add(cloneInternal);
}
return l;
}
}

View File

@ -0,0 +1,24 @@
package com.rits.cloning;
import java.util.LinkedList;
import java.util.Map;
/**
* @author kostantinos.kougios
*
* 21 May 2009
*/
public class FastClonerLinkedList implements IFastCloner
{
@SuppressWarnings({ "unchecked", "rawtypes" })
public Object clone(final Object t, final IDeepCloner cloner, final Map<Object, Object> clones) {
final LinkedList al = (LinkedList) t;
final LinkedList l = new LinkedList();
for (final Object o : al)
{
final Object cloneInternal = cloner.deepClone(o, clones);
l.add(cloneInternal);
}
return l;
}
}

View File

@ -0,0 +1,25 @@
package com.rits.cloning;
import java.util.Map;
import java.util.TreeMap;
/**
* @author kostantinos.kougios
*
* 21 May 2009
*/
public class FastClonerTreeMap implements IFastCloner
{
@SuppressWarnings({ "unchecked", "rawtypes" })
public Object clone(final Object t, final IDeepCloner cloner, final Map<Object, Object> clones) {
final TreeMap<Object, Object> m = (TreeMap) t;
final TreeMap result = new TreeMap(m.comparator());
for (final Map.Entry e : m.entrySet())
{
final Object key = cloner.deepClone(e.getKey(), clones);
final Object value = cloner.deepClone(e.getValue(), clones);
result.put(key, value);
}
return result;
}
}

View File

@ -0,0 +1,20 @@
package com.rits.cloning;
import java.util.Map;
/**
* used by fast cloners to deep clone objects
*
* @author kostas.kougios Date 24/06/14
*/
public interface IDeepCloner {
/**
* deep clones o
*
* @param o the object to be deep cloned
* @param clones pass on the same map from IFastCloner
* @param <T> the type of o
* @return a clone of o
*/
<T> T deepClone(final T o, final Map<Object, Object> clones);
}

View File

@ -0,0 +1,14 @@
package com.rits.cloning;
import java.lang.reflect.Field;
/**
* @author: kostas.kougios
* Date: 06/08/13
*/
public interface IDumpCloned
{
void startCloning(Class<?> clz);
void cloning(Field field, Class<?> clz);
}

View File

@ -0,0 +1,14 @@
package com.rits.cloning;
import java.util.Map;
/**
* allows a custom cloner to be created for a specific class.
* (it has to be registered with Cloner)
*
* @author kostantinos.kougios
* 21 May 2009
*/
public interface IFastCloner {
public Object clone(Object t, IDeepCloner cloner, Map<Object, Object> clones);
}

View File

@ -0,0 +1,12 @@
package com.rits.cloning;
/**
* @author kostantinos.kougios
*
* 15 Nov 2010
*/
public interface IFreezable
{
public boolean isFrozen();
}

View File

@ -0,0 +1,11 @@
package com.rits.cloning;
/**
* @author kostantinos.kougios
*
* 17 Jul 2012
*/
public interface IInstantiationStrategy
{
<T> T newInstance(final Class<T> c);
}

View File

@ -0,0 +1,25 @@
package com.rits.cloning;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* marks the specific class as immutable and the cloner avoids cloning it
*
* @author kostantinos.kougios
*
* 24 Mar 2011
*/
@Target(TYPE)
@Retention(RUNTIME)
public @interface Immutable
{
/**
* by default all subclasses of the @Immutable class are not immutable. This can override it.
* @return true for subclasses of @Immutable class to be regarded as immutable from the cloner
*/
boolean subClass() default false;
}

View File

@ -0,0 +1,26 @@
package com.rits.cloning;
import org.objenesis.Objenesis;
import org.objenesis.ObjenesisStd;
/**
* @author kostantinos.kougios
*
* 17 Jul 2012
*/
public class ObjenesisInstantiationStrategy implements IInstantiationStrategy
{
private final Objenesis objenesis = new ObjenesisStd();
public <T> T newInstance(Class<T> c)
{
return objenesis.newInstance(c);
}
private static ObjenesisInstantiationStrategy instance = new ObjenesisInstantiationStrategy();
public static ObjenesisInstantiationStrategy getInstance()
{
return instance;
}
}

View File

@ -0,0 +1,73 @@
package com.rits.perspectives;
import java.util.Collection;
import com.rits.cloning.Cloner;
/**
* Perspectives: an object instance of a class behaving differently according to the "view angle".
*
* @author kostantinos.kougios
*
* 30 Nov 2009
*/
public class Perspectives
{
private final Cloner cloner;
public Perspectives(final Cloner cloner)
{
this.cloner = cloner;
}
/**
* Sample: if o is an instance of Product and c is OrderedProduct.class then this returns
* and instance of OrderedProduct.class which has equal field values to those of the instance of Product.
* In other words, the returned instance of OrderedProduct.class is the Product instance from the perspective
* of an OrderedProduct
*
* View an object o from the perspective of class c. (view o as an instance of c). c must be instanceof o.getClass()
*
* @param <T> the object
* @param <E> this will be the returned type and it must be instanceof T. All properties of o will be copied to this instance.
* @param c the class of E. This is used to generate new instances of c
* @param o the object that must be viewed from a different perspective
* @return the E perspective of o
*/
public <T, E extends T> E viewAs(final Class<E> c, final T o)
{
if (o == null) return null;
if (o instanceof Collection<?>) throw new IllegalArgumentException("for collections please use viewCollectionAs() method. Invalid object " + o);
final E newInstance = cloner.fastCloneOrNewInstance(c);
cloner.copyPropertiesOfInheritedClass(o, newInstance);
return newInstance;
}
/**
* Sample: if o is a [ Products extends LinkedList<Product> ] then the returned instance
* is a [ OrderedProducts extends LinkedList<OrderedProduct> ].
*
* View a collection o from the perspective of collection E.
*
* NOTE: order of the items might not be preserved, depending on the collection type
*
* @param <T> the type of the collection o
* @param <I> the type of the elements of the collection o
* @param <E> the type of the perspective collection
* @param <NI> the type of the perspective's elements
* @param newCollection the collection to which the adapted instances should be added
* @param currentCollection the collection with the instances to be adapted
* @param perspectiveCollectionItemClass the class of the NI
* @return E, the collection from a different perspective or null if currentCollection is null
*/
public <I, NI extends I, T extends Collection<I>, E extends Collection<NI>> E viewCollectionAs(final E newCollection, final Class<NI> perspectiveCollectionItemClass, final T currentCollection)
{
if (currentCollection == null) return null;
for (final I item : currentCollection)
{
final NI newItem = viewAs(perspectiveCollectionItemClass, item);
newCollection.add(newItem);
}
return newCollection;
}
}

View File

@ -0,0 +1,744 @@
package org.nevec.rjm;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.security.ProviderException;
import org.warpgate.pi.calculator.Errore;
import org.warpgate.pi.calculator.Incognita;
import org.warpgate.pi.calculator.Incognite;
import org.warpgate.pi.calculator.Utils;
/**
* Square roots on the real line. These represent numbers which are a product of
* a (signed) fraction by a square root of a non-negative fraction. This might
* be extended to values on the imaginary axis by allowing negative values
* underneath the square root, but this is not yet implemented.
*
* @since 2011-02-12
* @author Richard J. Mathar
*/
public class NumeroAvanzato implements Cloneable {
/**
* The value of zero.
*/
public static final NumeroAvanzato ZERO = new NumeroAvanzato();
/**
* The value of one.
*/
public static final NumeroAvanzato ONE = new NumeroAvanzato(Rational.ONE, Rational.ONE);
/**
* Prefactor
*/
Rational pref;
private Incognite incognitex;
private Incognite incognitey;
private Incognite incognitez;
/**
* The number underneath the square root, always non-negative. The
* mathematical object has the value pref*sqrt(disc).
*/
Rational disc;
/**
* Default ctor, which represents the zero.
*
* @since 2011-02-12
*/
public NumeroAvanzato() {
pref = Rational.ZERO;
disc = Rational.ZERO;
incognitex = new Incognite();
incognitey = new Incognite();
incognitez = new Incognite();
}
/**
* ctor given the prefactor and the basis of the root. This creates an
* object of value a*sqrt(b).
*
* @param a
* the prefactor.
* @param b
* the discriminant.
* @throws Errore
* @since 2011-02-12
*/
public NumeroAvanzato(Rational a, Rational b) {
this.pref = a;
/*
* reject attempts to use a negative b
*/
if (b.signum() < 0)
throw new ProviderException("Not implemented: imaginary surds");
this.disc = b;
incognitex = new Incognite();
incognitey = new Incognite();
incognitez = new Incognite();
try {
normalize();
normalizeG();
} catch (Errore e) {
e.printStackTrace();
}
}
public NumeroAvanzato(Rational a, Rational b, Incognite x, Incognite y, Incognite z) {
this.pref = a;
/*
* reject attempts to use a negative b
*/
if (b.signum() < 0)
throw new ProviderException("Not implemented: imaginary surds");
this.disc = b;
incognitex = x;
incognitey = y;
incognitez = z;
try {
normalize();
normalizeG();
} catch (Errore e) {
e.printStackTrace();
}
}
/**
* ctor given the numerator and denominator of the root. This creates an
* object of value sqrt(a/b).
*
* @param a
* the numerator
* @param b
* the denominator.
* @since 2011-02-12
*/
public NumeroAvanzato(int a, int b) {
this(Rational.ONE, new Rational(a, b));
}
/**
* ctor given the value under the root. This creates an object of value
* sqrt(a).
*
* @param a
* the discriminant.
* @since 2011-02-12
*/
public NumeroAvanzato(BigInteger a) {
this(Rational.ONE, new Rational(a, BigInteger.ONE));
}
public NumeroAvanzato(Rational a) {
this(Rational.ONE, a);
}
/**
* Create a deep copy.
*
* @since 2011-02-12
*/
public NumeroAvanzato clone() {
Rational fclon = pref.clone();
Rational dclon = disc.clone();
Incognite incognitexb = incognitex;
Incognite incogniteyb = incognitey;
Incognite incognitezb = incognitez;
/*
* the main intent here is to bypass any attempt to reduce the
* discriminant by figuring out the square-free part in normalize(),
* which has already done in the current copy of the number.
*/
NumeroAvanzato cl = new NumeroAvanzato();
cl.pref = fclon;
cl.disc = dclon;
cl.incognitex = incognitexb;
cl.incognitey = incogniteyb;
cl.incognitez = incognitezb;
return cl;
} /* NumeroAvanzato.clone */
/**
* Add two surds of compatible discriminant.
*
* @param val
* The value to be added to this.
*/
public NumeroAvanzatoVec add(final NumeroAvanzato val) {
// zero plus somethings yields something
if (signum() == 0)
return new NumeroAvanzatoVec(val);
else if (val.signum() == 0)
return new NumeroAvanzatoVec(this);
else
// let the ctor of NumeroAvanzatoVec to the work
return new NumeroAvanzatoVec(this, val);
} /* NumeroAvanzato.add */
/**
* Multiply by another square root.
*
* @param val
* a second number of this type.
* @return the product of this with the val.
* @since 2011-02-12
*/
public NumeroAvanzato multiply(final NumeroAvanzato val) {
return new NumeroAvanzato(pref.multiply(val.pref), disc.multiply(val.disc), incognitex.multiply(val.incognitex),
incognitey.multiply(val.incognitey), incognitez.multiply(val.incognitez));
} /* NumeroAvanzato.multiply */
/**
* Multiply by a rational number.
*
* @param val
* the factor.
* @return the product of this with the val.
* @since 2011-02-15
*/
public NumeroAvanzato multiply(final Rational val) {
return new NumeroAvanzato(pref.multiply(val), disc, incognitex, incognitey, incognitez);
} /* NumeroAvanzato.multiply */
/**
* Multiply by a BigInteger.
*
* @param val
* a second number.
* @return the product of this with the value.
* @since 2011-02-12
*/
public NumeroAvanzato multiply(final BigInteger val) {
return new NumeroAvanzato(pref.multiply(val), disc, incognitex, incognitey, incognitez);
} /* NumeroAvanzato.multiply */
/**
* Multiply by an integer.
*
* @param val
* a second number.
* @return the product of this with the value.
* @since 2011-02-12
*/
public NumeroAvanzato multiply(final int val) {
BigInteger tmp = new BigInteger("" + val);
return multiply(tmp);
} /* NumeroAvanzato.multiply */
/**
* Compute the square.
*
* @return this value squared.
* @throws Errore
* @since 2011-02-12
*/
public NumeroAvanzato pow2() throws Errore {
NumeroAvanzato res = new NumeroAvanzato();
BigInteger a = pref.a;
BigInteger b = pref.b;
BigInteger c = disc.a;
BigInteger d = disc.b;
res.pref = new Rational(a.pow(2).multiply(c).multiply(d), b.pow(2).multiply(d));
res.disc = new Rational(0, 1);
res.normalize();
res.incognitex = incognitex;
res.incognitey = incognitey.multiply(incognitey);
res.incognitez = incognitez.multiply(incognitez);
return res;
} /* NumeroAvanzato.sqr */
/**
* Divide by another square root.
*
* @param val
* A second number of this type.
* @return The value of this/val
* @throws Errore
* @since 2011-02-12
*/
public NumeroAvanzato divide(final NumeroAvanzato val) throws Errore {
if (val.signum() == 0)
throw new ArithmeticException("Dividing " + toFancyString() + " through zero.");
NumeroAvanzato result = new NumeroAvanzato(pref.divide(val.pref), disc.divide(val.disc));
result.incognitex = incognitex.divide(val.incognitex);
result.incognitey = incognitey.divide(val.incognitey);
result.incognitez = incognitez.divide(val.incognitez);
result.normalize();
return result;
} /* NumeroAvanzato.divide */
private String toFancyString() throws Errore {
return new NumeroAvanzatoVec(this).toFancyString();
}
/**
* Divide by an integer.
*
* @param val
* a second number.
* @return the value of this/val
* @throws Errore
* @since 2011-02-12
*/
public NumeroAvanzato divide(final BigInteger val) throws Errore {
if (val.signum() == 0)
throw new ArithmeticException("Dividing " + toFancyString() + " through zero.");
return new NumeroAvanzato(pref.divide(val), disc);
} /* NumeroAvanzato.divide */
/**
* Divide by an integer.
*
* @param val
* A second number.
* @return The value of this/val
* @throws Errore
* @since 2011-02-12
*/
public NumeroAvanzato divide(int val) throws Errore {
if (val == 0)
throw new ArithmeticException("Dividing " + toFancyString() + " through zero.");
return new NumeroAvanzato(pref.divide(val), disc);
} /* NumeroAvanzato.divide */
/**
* Compute the negative.
*
* @return -this.
* @since 2011-02-12
*/
public NumeroAvanzato negate() {
/*
* This is trying to be quick, avoiding normalize(), by toggling the
* sign in a clone()
*/
NumeroAvanzato n = clone();
n.pref = n.pref.negate();
return n;
} /* NumeroAvanzato.negate */
/**
* Absolute value.
*
* @return The absolute (non-negative) value of this.
* @since 2011-02-12
*/
public NumeroAvanzato abs() {
return new NumeroAvanzato(pref.abs(), disc);
}
/**
* Compares the value of this with another constant.
*
* @param val
* the other constant to compare with
* @return -1, 0 or 1 if this number is numerically less than, equal to, or
* greater than val.
* @throws Errore
* @since 2011-02-12
*/
public int signumComparedTo(final NumeroAvanzato val) throws Errore {
/*
* Since we keep the discriminant positive, the rough estimate comes
* from comparing the signs of the prefactors.
*/
final int sig = signum();
final int sigv = val.signum();
if (sig < 0 && sigv >= 0)
return -1;
if (sig > 0 && sigv <= 0)
return 1;
if (sig == 0 && sigv == 0)
return 0;
if (sig == 0 && sigv > 0)
return -1;
if (sig == 0 && sigv < 0)
return 1;
/*
* Work out the cases of equal sign. Compare absolute values by
* comparison of the squares which is forwarded to the comparison of the
* Rational class.
*/
final Rational this2 = pow2().pref;
final Rational val2 = val.pow2().pref;
final int c2 = this2.compareTo(val2);
if (c2 == 0)
return 0;
/*
* If both values have negative sign, the one with the smaller square is
* the larger number.
*/
else if (sig > 0 && c2 > 0 || sig < 0 && c2 < 0)
return 1;
else
return -1;
} /* NumeroAvanzato.compareTo */
/**
* Return a string in the format (number/denom)*()^(1/2). If the
* discriminant equals 1, print just the prefactor.
*
* @return the human-readable version in base 10
* @since 2011-02-12
*/
public String toString() {
try {
return toFancyString();
} catch (Errore e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*
if (disc.compareTo(Rational.ONE) != 0 && disc.compareTo(Rational.ZERO) != 0)
return ("(" + pref.toString() + ")*(" + disc.toString() + ")^(1/2)");
else
return pref.toString();
*/
return "err";
} /* NumeroAvanzato.toString */
/**
* Return a double value representation.
*
* @return The value with double precision.
* @since 2011-02-12
*/
public double doubleValue() {
/*
* First compute the square to prevent overflows if the two pieces of
* the prefactor and the discriminant are of very different magnitude.
*/
Rational p2 = pref.pow(2).multiply(disc);
System.out.println("dv sq " + p2.toString());
double res = p2.doubleValue();
System.out.println("dv sq " + res);
return (pref.signum() >= 0) ? Math.sqrt(res) : -Math.sqrt(res);
} /* NumeroAvanzato.doubleValue */
/**
* Return a float value representation.
*
* @return The value with single precision.
* @since 2011-02-12
*/
public float floatValue() {
return (float) (doubleValue());
} /* NumeroAvanzato.floatValue */
/**
* True if the value is integer. Equivalent to the indication whether a
* conversion to an integer can be exact.
* @param hasBigIntegerVariables
*
* @since 2011-02-12
*/
public boolean isBigInteger(boolean hasBigIntegerVariables) {
if (pref.isBigInteger() && (disc.signum() == 0 || disc.compareTo(Rational.ONE) == 0)) {
if (disc.signum() != 0 && incognitex.count() > 0) {
return false;
}
if (hasBigIntegerVariables == false && incognitey.count() > 0) {
return false;
}
if (pref.b.compareTo(BigInteger.ZERO) != 0 && disc.b.compareTo(BigInteger.ZERO) != 0 && incognitez.count() > 0) {
return false;
}
return true;
}
return false;
} /* NumeroAvanzato.isBigInteger */
public boolean isRational(boolean hasRationalVariables) {
if (disc.signum() == 0 || disc.compareTo(new Rational(1, 1)) == 0) {
if (incognitex.count() > 0) {
return false;
} else if (hasRationalVariables == false) {
if (incognitey.count() > 0 || incognitez.count() > 0) {
return false;
}
}
if (this.pref.b.compareTo(new BigInteger("10000")) > 0) {
return false;
}
return true;
}
return false;
} /* NumeroAvanzato.isRational */
public boolean isTooPreciseRational(boolean hasRationalVariables) {
if (disc.signum() == 0 || disc.compareTo(new Rational(1, 1)) == 0) {
if (incognitex.count() > 0) {
return false;
} else if (hasRationalVariables == false) {
if (incognitey.count() > 0 || incognitez.count() > 0) {
return false;
}
}
if (this.pref.b.compareTo(new BigInteger("10000")) > 0) {
return true;
}
return false;
}
return false;
} /* NumeroAvanzato.isRational */
/**
* Convert to a rational value if possible
* @throws Errore
*
* @since 2012-02-15
*/
public Rational toRational(boolean hasRationalVariables) throws Errore {
if (isRational(hasRationalVariables) || isTooPreciseRational(hasRationalVariables))
return pref;
else
throw new ArithmeticException("Undefined conversion " + toFancyString() + " to Rational.");
} /* NumeroAvanzato.toRational */
public Rational toRational() throws Errore {
if (isRational(true))
return pref;
else
throw new ArithmeticException("Undefined conversion " + toFancyString() + " to Rational.");
}
/**
* The sign: 1 if the number is >0, 0 if ==0, -1 if <0
*
* @return the signum of the value.
* @since 2011-02-12
*/
public int signum() {
/*
* Since the disc is kept positive, this is the same as the sign of the
* prefactor. This works because a zero discriminant is always copied
* over to the prefactor, not hidden.
*/
return pref.signum();
} /* NumeroAvanzato.signum */
/**
* Normalize to squarefree discriminant.
* @throws Errore
*
* @since 2011-02-12
*/
protected void normalize() throws Errore {
/*
* Move squares out of the numerator and denominator of the discriminant
*/
if (disc.signum() != 0) {
/*
* square-free part of the numerator: numer = numC*some^2
*/
BigInteger numC = BigIntegerMath.core(disc.numer());
/*
* extract the perfect square of the numerator
*/
BigInteger sq = disc.numer().divide(numC);
/*
* extract the associated square root
*/
BigInteger sqf = BigIntegerMath.isqrt(sq);
/*
* move sqf over to the pre-factor
*/
pref = pref.multiply(sqf);
BigInteger denC = BigIntegerMath.core(disc.denom());
sq = disc.denom().divide(denC);
sqf = BigIntegerMath.isqrt(sq);
try {
pref = pref.divide(sqf);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
disc = new Rational(numC, denC);
if (disc.b.compareTo(BigInteger.ZERO) == 0 || disc.a.compareTo(BigInteger.ZERO) == 0 || pref.a.compareTo(BigInteger.ZERO) == 0) {
incognitex = new Incognite();
incognitey = new Incognite();
}
if (disc.b.compareTo(BigInteger.ZERO) == 0 || pref.b.compareTo(BigInteger.ZERO) == 0) {
incognitez = new Incognite();
}
if (incognitey.compareTo(incognitez)) {
incognitey = new Incognite();
incognitez = new Incognite();
}
/**/
Incognite[] incognitetemp = new Incognite[]{incognitex, incognitey, incognitez};
incognitetemp = Incognite.normalizeBigSurdVariables(incognitetemp);
incognitex = incognitetemp[0];
incognitey = incognitetemp[1];
incognitez = incognitetemp[2];
/**/
} else {
pref = Rational.ZERO;
incognitex = new Incognite();
incognitey = new Incognite();
incognitez = new Incognite();
}
} /* NumeroAvanzato.normalize */
/**
* Normalize to coprime numerator and denominator in prefactor and
* discriminant
* @throws Errore
*
* @since 2011-02-12
*/
protected void normalizeG() throws Errore {
/*
* Is there a common factor between the numerator of the prefactor and
* the denominator of the discriminant ?
*/
BigInteger d = pref.numer().abs().gcd(disc.denom());
if (d.compareTo(BigInteger.ONE) > 0) {
try {
pref = pref.divide(d);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*
* instead of multiplying with the square of d, using two steps
* offers a change to recognize the common factor..
*/
disc = disc.multiply(d);
disc = disc.multiply(d);
}
/*
* Is there a common factor between the denominator of the prefactor and
* the numerator of the discriminant ?
*/
d = pref.denom().gcd(disc.numer());
if (d.compareTo(BigInteger.ONE) > 0) {
pref = pref.multiply(d);
/*
* instead of dividing through the square of d, using two steps
* offers a change to recognize the common factor..
*/
disc = disc.divide(d);
disc = disc.divide(d);
}
} /* NumeroAvanzato.normalizeG */
/**
* Return the approximate floating point representation.
*
* @param mc
* Description of the accuracy needed.
* @return A representation with digits valid as described by mc
* @since 2012-02-15
*/
public BigDecimal BigDecimalValue(MathContext mc) {
/*
* the relative error of the result equals the relative error of the
* prefactor plus half of the relative error of the discriminant. So
* adding 3 digits temporarily is sufficient.
*/
final MathContext locmc = new MathContext(mc.getPrecision() + 3, mc.getRoundingMode());
/*
* first the square root of the discriminant
*/
BigDecimal sqrdis = BigDecimalMath.sqrt(disc.BigDecimalValue(locmc), locmc);
/*
* Then multiply by the prefactor. If sqrdis is a terminating decimal
* fraction, we prevent early truncation of the result by truncating
* later.
*/
BigDecimal res = sqrdis.multiply(pref.BigDecimalValue(mc));
return BigDecimalMath.scalePrec(res, mc);
} /* BigDecimalValue */
@Override
public boolean equals(Object val) {
if (val instanceof NumeroAvanzato) {
NumeroAvanzato na = (NumeroAvanzato) val;
try {
if (pow2().pref == na.pow2().pref) {
if (pow2().pref == Rational.ZERO) {
return true;
} else {
if (incognitex == na.incognitex) {
if (incognitey == na.incognitey) {
if (incognitez == na.incognitez) {
return true;
}
}
}
}
}
} catch (Errore e) {
e.printStackTrace();
}
}
return false;
}
public Incognite getIncognitex() {
if (incognitex == null) {
return incognitex;
}
return incognitex.clone();
}
public NumeroAvanzato setIncognitex(Incognite incognitex) {
NumeroAvanzato result = this.clone();
result.incognitex = incognitex;
return result;
}
public Incognite getIncognitey() {
if (incognitey == null) {
return incognitey;
}
return incognitey.clone();
}
public NumeroAvanzato setIncognitey(Incognite incognitey) {
NumeroAvanzato result = this.clone();
result.incognitey = incognitey;
return result;
}
public Incognite getIncognitez() {
if (incognitez == null) {
return incognitez;
}
return incognitez.clone();
}
public NumeroAvanzato setIncognitez(Incognite incognitez) {
NumeroAvanzato result = this.clone();
result.incognitez = incognitez;
return result;
}
public NumeroAvanzato divideUnsafe(BigInteger denominator) {
try {
return divide(denominator);
} catch (Errore e) {
e.printStackTrace();
return new NumeroAvanzato();
}
}
} /* NumeroAvanzato */

View File

@ -0,0 +1,752 @@
package org.nevec.rjm;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.util.Comparator;
import java.util.Vector;
import org.warpgate.pi.calculator.Errore;
import org.warpgate.pi.calculator.Incognita;
import org.warpgate.pi.calculator.Incognite;
import org.warpgate.pi.calculator.Utils;
/**
* A NumeroAvanzatoVec represents an algebraic sum or differences of values which each
* term an instance of NumeroAvanzato. This mainly means that sums or differences of
* two NumeroAvanzato (or two NumeroAvanzatoVec) can be represented (exactly) as a NumeroAvanzatoVec.
*
* @since 2012-02-15
* @author Richard J. Mathar
*/
public class NumeroAvanzatoVec implements Comparable<NumeroAvanzatoVec> {
/**
* The value of zero.
*/
public static final NumeroAvanzatoVec ZERO = new NumeroAvanzatoVec();
/**
* The value of one.
*/
public static final NumeroAvanzatoVec ONE = new NumeroAvanzatoVec(NumeroAvanzato.ONE);
/**
* Internal representation: Each term as a single NumeroAvanzato. The value zero is
* represented by an empty vector.
*/
Vector<NumeroAvanzato> terms;
/**
* Default ctor, which represents the zero.
*
* @since 2012-02-15
*/
public NumeroAvanzatoVec() {
terms = new Vector<NumeroAvanzato>();
} /* ctor */
/**
* ctor given the value of a NumeroAvanzato.
*
* @param a
* The value to be represented by this vector.
* @since 2012-02-15
*/
public NumeroAvanzatoVec(NumeroAvanzato a) {
terms = new Vector<NumeroAvanzato>(1);
terms.add(a);
} /* ctor */
/**
* ctor given two values, which (when added) represent this number a+b.
*
* @param a
* The value to be represented by the first term of the vector.
* @param b
* The value to be represented by the second term of the vector.
* @since 2012-02-15
*/
public NumeroAvanzatoVec(NumeroAvanzato a, NumeroAvanzato b) {
terms = new Vector<NumeroAvanzato>(2);
terms.add(a);
terms.add(b);
try {
normalize();
} catch (Errore e) {
e.printStackTrace();
}
} /* ctor */
/**
* Combine terms that can be written as a single surd. This unites for
* example the terms sqrt(90) and sqrt(10) to 4*sqrt(10).
* @throws Errore
*
* @since 2012-02-15
*/
protected void normalize() throws Errore {
/*
* nothing to be done if at most one term
*/
if (terms.size() <= 1)
return;
Vector<NumeroAvanzato> newter = new Vector<NumeroAvanzato>();
newter.add(terms.firstElement());
/*
* add j-th element to the existing vector and combine were possible
*/
for (int j = 1; j < terms.size(); j++) {
NumeroAvanzato todo = terms.elementAt(j);
boolean merged = false;
for (int ex = 0; ex < newter.size(); ex++) {
NumeroAvanzato v = newter.elementAt(ex);
/*
* try to merge terms[j] and newter[ex]. todo = r * v with r a
* rational number is needed. Replaces v with v+todo = v*(1+r)
* if this reduction works.
*/
NumeroAvanzato r = todo.divide(v);
if ((r.isRational(true) || r.isTooPreciseRational(true)) && todo.getIncognitex().compareTo(v.getIncognitex()) && todo.getIncognitey().compareTo(v.getIncognitey()) && todo.getIncognitez().compareTo(v.getIncognitez())) {
/* compute r+1 */
Rational newpref = r.toRational(true).add(1);
/*
* eliminate accidental zeros; overwrite with v*(1+r).
*/
if (newpref.compareTo(Rational.ZERO) == 0)
newter.removeElementAt(ex);
else {
v = v.multiply(newpref);
newter.setElementAt(v, ex);
}
merged = true;
break;
}
}
/*
* append if none of the existing elements matched
*/
if (!merged)
newter.add(todo);
}
newter.sort(new Comparator<NumeroAvanzato>() {
@Override
public int compare(NumeroAvanzato o1, NumeroAvanzato o2) {
int index1 = Incognite.priorità(o1.getIncognitex().sqrt().multiply(o1.getIncognitey()).divide(o1.getIncognitez()));
int index2 = Incognite.priorità(o2.getIncognitex().sqrt().multiply(o2.getIncognitey()).divide(o2.getIncognitez()));
return index2-index1;
}
});
/* overwrite old version */
terms = newter;
} /* normalize */
/**
* Compare algebraic value with oth. Returns -1, 0 or +1 depending on
* whether this is smaller, equal to or larger than oth.
*
* @param oth
* The value with which this is to be compared.
* @return 0 or +-1.
* @since 2012-02-15
*/
public int compareTo(NumeroAvanzatoVec oth) {
NumeroAvanzatoVec diff;
try {
diff = this.subtract(oth);
return diff.signum();
} catch (Errore e) {
e.printStackTrace();
return 0;
}
} /* compareTo */
/**
* Sign function. Returns -1, 0 or +1 depending on whether this is smaller,
* equal to or larger than zero.
*
* @return 0 or +-1.
* @throws Errore
* @since 2012-02-15
*/
public int signum() throws Errore {
/*
* the case of zero is unique, because no (reduced) vector of surds
* other than the one element 0 itself can add/subtract to zero.
*/
if (terms.size() == 0)
return 0;
/*
* if there is one term: forward to the signum function of NumeroAvanzato
*/
if (terms.size() == 1)
return terms.firstElement().signum();
/*
* if all terms have a common sign: take that one offsig is the index of
* the first "offending" term in the sense that its sign doese not agree
* with the term[0].
*/
int sig0 = terms.elementAt(0).signum();
int offsig = 1;
for (; offsig < terms.size(); offsig++)
if (terms.elementAt(offsig).signum() != sig0)
break;
if (offsig >= terms.size())
return sig0;
/*
* if there are two terms (now known to have different sign): forward to
* the comparison of the two elements as NumeroAvanzatos
*/
if (terms.size() == 2)
return terms.elementAt(0).signumComparedTo(terms.elementAt(1).negate());
/*
* if there are three terms, move the one with the offending sign to the
* other side and square both sides (which looses the sign) to remove
* all but one surds. The difference of the squared sides contains at
* most two terms, which reduces to the case above. t(0)+t(offbar) <>
* -t(offs)
*/
if (terms.size() == 3) {
NumeroAvanzatoVec lhs;
if (offsig == 2)
lhs = new NumeroAvanzatoVec(terms.elementAt(0), terms.elementAt(1));
else
lhs = new NumeroAvanzatoVec(terms.elementAt(0), terms.elementAt(2));
lhs = lhs.sqr();
/*
* Strange line: this line isn't used, but it's present in this code!
*
*
*
NumeroAvanzato rhs = new NumeroAvanzato(terms.elementAt(offsig).sqr(), Rational.ONE);
*
*
*
*/
if (lhs.compareTo(lhs) > 0)
/*
* dominating sign was t(0)+t(offbar)
*/
return terms.elementAt(0).signum();
else
return terms.elementAt(offsig).signum();
}
/*
* for a larger number of terms: take a floating point representation
* with a small but correct number of digits, and resume with the sign
* of that one.
*/
return (floatValue() > 0.) ? 1 : -1;
} /* signum */
/**
* Construct an approximate floating point representation
*
* @param mc
* The intended accuracy of the result.
* @return A truncated version with the precision described by mc
*/
public BigDecimal BigDecimalValue(MathContext mc) {
/*
* simple cases with one term forwarded to the NumeroAvanzato class
*/
if (terms.size() == 0)
return BigDecimal.ZERO;
else if (terms.size() == 1) {
return terms.firstElement().BigDecimalValue(mc);
}
/*
* To reduce cancellation errors, loop over increasing local precision
* until we are stable to the required result. Keep the old (less
* precise) estimate in res[0], and the newer, more precise in res[1].
*/
BigDecimal[] res = new BigDecimal[2];
res[0] = BigDecimal.ZERO;
for (int addpr = 1;; addpr += 3) {
MathContext locmc = new MathContext(mc.getPrecision() + addpr, mc.getRoundingMode());
res[1] = BigDecimal.ZERO;
for (NumeroAvanzato j : terms)
res[1] = BigDecimalMath.addRound(res[1], j.BigDecimalValue(locmc));
if (addpr > 1) {
BigDecimal err = res[1].subtract(res[0]).abs();
int prec = BigDecimalMath.err2prec(res[1], err);
if (prec == Integer.MIN_VALUE) {
break;
}
if (prec > mc.getPrecision())
break;
}
res[0] = res[1];
}
return BigDecimalMath.scalePrec(res[1], mc);
} /* BigDecimalValue */
/**
* Construct an approximate floating point representation
*
* @return A truncated version with the precision described by mc
*/
public double doubleValue() {
BigDecimal bd = BigDecimalValue(MathContext.DECIMAL128);
return bd.doubleValue();
} /* doubleValue */
/**
* Construct an approximate floating point representation
*
* @return A truncated version with the precision described by mc
*/
public double floatValue() {
BigDecimal bd = BigDecimalValue(MathContext.DECIMAL64);
return bd.floatValue();
} /* floatValue */
/**
* Add two vectors algebraically.
*
* @param val
* The value to be added to this.
* @return The new value representing this+val.
* @throws Errore
*/
public NumeroAvanzatoVec add(final NumeroAvanzatoVec val) throws Errore {
NumeroAvanzatoVec sum = new NumeroAvanzatoVec();
/*
* concatenate the vectors and eliminate common overlaps
*/
for (NumeroAvanzato term : terms) {
if (term.signumComparedTo(NumeroAvanzato.ZERO) != 0) {
sum.terms.add(term);
}
}
for (NumeroAvanzato term : val.terms) {
if (term.signumComparedTo(NumeroAvanzato.ZERO) != 0) {
sum.terms.add(term);
}
}
sum.normalize();
return sum;
} /* add */
/**
* Add two vectors algebraically.
*
* @param val
* The value to be added to this.
* @return The new value representing this+val.
* @throws Errore
*/
public NumeroAvanzatoVec add(final NumeroAvanzato val) throws Errore {
NumeroAvanzatoVec sum = new NumeroAvanzatoVec();
/*
* concatenate the vectors and eliminate common overlaps
*/
sum.terms.addAll(terms);
sum.terms.add(val);
sum.normalize();
return sum;
} /* add */
/**
* Subtract another number.
*
* @param val
* The value to be subtracted from this.
* @return The new value representing this-val.
* @throws Errore
*/
public NumeroAvanzatoVec subtract(final NumeroAvanzatoVec val) throws Errore {
NumeroAvanzatoVec sum = new NumeroAvanzatoVec();
/*
* concatenate the vectors and eliminate common overlaps
*/
sum.terms.addAll(terms);
for (NumeroAvanzato s : val.terms)
sum.terms.add(s.negate());
sum.normalize();
return sum;
} /* subtract */
/**
* Subtract another number.
*
* @param val
* The value to be subtracted from this.
* @return The new value representing this-val.
* @throws Errore
*/
public NumeroAvanzatoVec subtract(final NumeroAvanzato val) throws Errore {
NumeroAvanzatoVec sum = new NumeroAvanzatoVec();
/*
* concatenate the vectors and eliminate common overlaps
*/
sum.terms.addAll(terms);
sum.terms.add(val.negate());
sum.normalize();
return sum;
} /* subtract */
/**
* Compute the negative.
*
* @return -this.
* @since 2012-02-15
*/
public NumeroAvanzatoVec negate() {
/*
* accumulate the negated elements of term one by one
*/
NumeroAvanzatoVec resul = new NumeroAvanzatoVec();
for (NumeroAvanzato s : terms)
resul.terms.add(s.negate());
/*
* no normalization step here, because the negation of all terms does
* not introduce new common factors
*/
return resul;
} /* negate */
/**
* Compute the square.
*
* @return this value squared.
* @throws Errore
* @since 2012-02-15
*/
public NumeroAvanzatoVec sqr() throws Errore {
/*
* Binomial expansion. First the sum of the terms squared, then 2 times
* the mixed products.
*/
NumeroAvanzatoVec resul = new NumeroAvanzatoVec();
for (int i = 0; i < terms.size(); i++)
resul.terms.add(terms.elementAt(i).pow2());
for (int i = 0; i < terms.size() - 1; i++)
for (int j = i + 1; j < terms.size(); j++)
resul.terms.add(terms.elementAt(i).multiply(terms.elementAt(j)).multiply(2));
resul.normalize();
return resul;
} /* sqr */
/**
* Multiply by another square root.
*
* @param val
* a second number of this type.
* @return the product of this with the val.
* @throws Errore
* @since 2011-02-12
*/
public NumeroAvanzatoVec multiply(final NumeroAvanzato val) throws Errore {
NumeroAvanzatoVec resul = new NumeroAvanzatoVec();
for (NumeroAvanzato s : terms)
resul.terms.add(s.multiply(val));
resul.normalize();
return resul;
} /* multiply */
public NumeroAvanzatoVec multiply(final NumeroAvanzatoVec val) throws Errore {
NumeroAvanzatoVec resul = new NumeroAvanzatoVec();
for (NumeroAvanzato s : terms) {
for (NumeroAvanzato s2 : val.terms) {
resul = resul.add(s.multiply(s2));
}
}
return resul;
} /* multiply */
public NumeroAvanzatoVec divide(final NumeroAvanzato val) throws Errore {
NumeroAvanzatoVec resul = new NumeroAvanzatoVec();
for (NumeroAvanzato s : terms) {
resul.terms.add(s.divide(val));
}
resul.normalize();
return resul;
} /* divide */
public NumeroAvanzatoVec divide(final NumeroAvanzatoVec val) throws Errore {
NumeroAvanzatoVec resul = new NumeroAvanzatoVec();
resul.terms = this.terms;
for (NumeroAvanzato s : val.terms) {
resul = resul.divide(s);
}
return resul;
} /* divide */
/**
* True if the value is rational. Equivalent to the indication whether a
* conversion to a Rational can be exact.
*
* @since 2011-02-12
*/
public boolean isRational(boolean hasRationalVariables) {
boolean val = false;
for (NumeroAvanzato s : terms) {
val = s.isRational(hasRationalVariables);
if (val == false) {
break;
}
}
return val;
} /* NumeroAvanzatoVec.isRational */
public boolean isNumeroAvanzato() {
return (this.terms.size() <= 1);
}
/**
* True if the value is BigInteger. Equivalent to the indication whether a
* conversion to a BigInteger can be exact.
*
* @since 2011-02-12
*/
public boolean isBigInteger(boolean hasBigIntegerVariables) {
boolean val = false;
for (NumeroAvanzato s : terms) {
val = s.isBigInteger(hasBigIntegerVariables);
if (val == true) {
if (s.getIncognitex().count() > 0 || s.getIncognitez().count() > 0) {
val = false;
}
}
if (val == false) {
break;
}
}
return val;
} /* NumeroAvanzatoVec.isRational */
/**
* Convert to a rational value if possible
*
* @since 2012-02-15
*/
public Rational toRational(boolean hasRationalVariables) {
Rational rat = Rational.ZERO;
if (isRational(hasRationalVariables) == false)
throw new ArithmeticException("Undefined conversion " + toString() + " to Rational.");
for (NumeroAvanzato s : terms) {
rat = rat.add(s.pref);
}
return rat;
} /* NumeroAvanzato.toRational */
/**
* Convert to a BigInteger value if possible
*
* @since 2012-02-15
*/
public BigInteger toBigInteger(boolean hasBigIntegerVariables) {
BigDecimal tmp = BigDecimal.ZERO.setScale(Utils.scale, Utils.scaleMode);
if (isBigInteger(hasBigIntegerVariables) == false)
throw new ArithmeticException("Undefined conversion " + toString() + " to Rational.");
for (NumeroAvanzato s : terms) {
tmp = BigDecimalMath.addRound(tmp, s.pref.BigDecimalValue(new MathContext(Utils.scale, Utils.scaleMode2)));
}
return tmp.toBigInteger();
} /* NumeroAvanzato.toRational */
/**
* Convert to a BigDecimal value if possible
*
* @since 2012-02-15
*/
public BigDecimal toBigDecimal() {
BigDecimal tmp = BigDecimal.ZERO.setScale(Utils.scale, Utils.scaleMode);
for (NumeroAvanzato s : terms) {
tmp = BigDecimalMath.addRound(tmp, s.BigDecimalValue(new MathContext(Utils.scale, Utils.scaleMode2)));
}
return tmp;
} /* NumeroAvanzato.toBigDecimal */
public NumeroAvanzato toNumeroAvanzato() {
if (this.terms.size() == 0) {
return NumeroAvanzato.ZERO;
}
return this.terms.get(0);
}
/**
* Return a string in the format (number/denom)*()^(1/2). If the
* discriminant equals 1, print just the prefactor.
*
* @return the human-readable version in base 10
* @since 2012-02-16
*/
public String toString() {
/*
* simple cases with one term forwarded to the NumeroAvanzato class
*/
return toFancyString();
/*
if (terms.size() == 0)
return new String("0");
else {
String s = new String();
for (int t = 0; t < terms.size(); t++) {
NumeroAvanzato bs = terms.elementAt(t);
if (bs.signum() > 0)
s += "+";
s += bs.toString();
}
return s;
}
*/
} /* toString */
public String toFancyString() {
if (terms.size() == 0) {
return new String("0");
} else if (terms.size() == 1 && terms.elementAt(0).isTooPreciseRational(true)) {
String s = "";
NumeroAvanzato bs = terms.elementAt(0).clone();
String num = bs.BigDecimalValue(new MathContext(Utils.resultScale, Utils.scaleMode2)).toEngineeringString();
if (num.contains("E")) {
s += "("+num.replace("E+", "*10^")+")";
} else {
s += num;
}
s += bs.getIncognitey().toString();
return s;
} else {
BigInteger denominator = BigInteger.ONE;
Incognite incognitedenom = new Incognite();
for (int i = 0; i < terms.size(); i++) {
denominator = BigIntegerMath.lcm(denominator, terms.elementAt(i).pref.b);
//denominator = denominator.multiply(terms.elementAt(i).pref.b);
Incognite iz = terms.elementAt(i).getIncognitez();
incognitedenom = Incognite.lcm(incognitedenom, iz);
}
String s = "";
if (denominator.abs().compareTo(new BigInteger("10000")) > 0) {
for (int i = 0; i < terms.size(); i++) {
NumeroAvanzato bs = terms.elementAt(i).clone();
String num = bs.BigDecimalValue(new MathContext(Utils.resultScale, Utils.scaleMode2)).toEngineeringString().replaceAll("\\.0+$", "").replaceAll("\\.0+E", "E");
if (num.contains("E")) {
if (bs.signum() > 0) {
s += "+";
}
num = num.replace("E+", "*10^")+")";
if (num.contains("*10^1)")) {
num = num.replace("*10^1)", ")");
} else {
num = "("+num;
}
s += num;
} else {
if (bs.signum() > 0) {
s += "+";
}
s += num;
}
s += bs.getIncognitey().toString();
}
return s;
}
if (denominator.compareTo(BigInteger.ONE) != 0 || incognitedenom.count() > 0) {
if (terms.size() == 1 && terms.get(0).multiply(denominator).isBigInteger(true) == false) {
s += "(";
}
}
for (int t = 0; t < terms.size(); t++) {
NumeroAvanzato bs = terms.elementAt(t).clone();
bs = bs.setIncognitey(bs.getIncognitey().divide(bs.getIncognitez()));
bs = bs.setIncognitey(bs.getIncognitey().multiply(incognitedenom));
bs = bs.multiply(denominator);
bs = bs.setIncognitez(incognitedenom);
bs.pref = new Rational(bs.pref.a, BigInteger.ONE);
if (bs.signum() > 0 && t > 0)
s += "+";
if (bs.isBigInteger(true)) {
String numb;
try {
numb = bs.toRational(true).a.toString();
} catch (Errore e) {
// TODO Auto-generated catch block
e.printStackTrace();
numb = "";
}
String incognite = bs.getIncognitey().toString();
if (((numb.equals("1") || numb.equals("-1")) == false && incognite.length() > 0) || incognite.length() == 0) {
s += numb;
} else if (numb.equals("-1")) {
s += "-";
}
s +=incognite;
} else if (bs.isRational(true) || bs.isTooPreciseRational(true)) {
try {
s += bs.toRational(true).toString();
} catch (Errore e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
s += bs.getIncognitey().toString();
} else {
BigInteger numerator = bs.pref.numer();
if ((numerator.compareTo(BigInteger.ONE) != 0 || bs.getIncognitey().count() > 0) && (bs.disc.compareTo(BigInteger.ONE) != 0 || bs.getIncognitex().count() > 0)) {
if (((bs.getIncognitey().count() > 0) || (bs.getIncognitey().count() == 0 && numerator.toString().length() > 0))) {
if ((bs.getIncognitey().count() > 0 && (numerator.toString().equals("1") || numerator.toString().equals("-1")) == false) || bs.getIncognitey().count() == 0) {
s += numerator.toString();
} else if (numerator.toString().equals("-1")) {
s += "-";
}
}
//s += "(";
}
if (bs.disc.isInteger() && bs.getIncognitex().count() == 0) {
s += "Ⓐ(";
s += bs.disc.toString();
s += ")";
} else if((bs.disc.toString().equals("1") || bs.disc.toString().equals("-1")) && bs.getIncognitex().count() > 0) {
s += "Ⓐ(";
if (bs.disc.toString().equals("-1")) {
s += "-";
}
s += bs.getIncognitex().toString();
s += ")";
} else {
s += "Ⓐ("+bs.disc.toString()+bs.getIncognitex().toString()+")";
}
if ((numerator.compareTo(BigInteger.ONE) != 0 || bs.getIncognitey().count() > 0) && (bs.disc.compareTo(BigInteger.ONE) != 0 || bs.getIncognitex().count() > 0)) {
if (((bs.getIncognitey().count() > 0) || (bs.getIncognitey().count() == 0 && numerator.toString().length() > 0))) {
s += bs.getIncognitey().toString();
}
//s += "(";
}
if ((numerator.compareTo(BigInteger.ONE) != 0 || bs.getIncognitey().count() > 0) && (bs.disc.compareTo(BigInteger.ONE) != 0 || bs.getIncognitex().count() > 0)) {
//s += ")";
}
}
}
if (denominator.compareTo(BigInteger.ONE) != 0 || incognitedenom.count() > 0) {
if (terms.size() == 1 && terms.get(0).multiply(denominator).isBigInteger(true) == false) {
s += ")";
}
s += "/";
if ((incognitedenom.count() > 0 && (denominator.toString().equals("1") || denominator.toString().equals("-1")) == false) || incognitedenom.count() == 0) {
s += denominator;
} else if (denominator.toString().equals("-1")) {
s += "-";
}
s += incognitedenom.toString();
}
return s;
}
}
} /* NumeroAvanzatoVec */

View File

@ -0,0 +1,696 @@
package org.warp.engine.lwjgl;
import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWFramebufferSizeCallback;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.glfw.GLFWWindowSizeCallback;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GLCapabilities;
import org.lwjgl.opengl.GLUtil;
import org.lwjgl.stb.STBTTAlignedQuad;
import org.lwjgl.stb.STBTTPackContext;
import org.lwjgl.stb.STBTTPackedchar;
import org.warpgate.pi.calculator.Calculator;
import org.warpgate.pi.calculator.Keyboard;
import org.warpgate.pi.calculator.Main;
import org.warpgate.pi.calculator.Utils;
import de.matthiasmann.twl.utils.PNGDecoder;
import de.matthiasmann.twl.utils.PNGDecoder.Format;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import static org.warp.engine.lwjgl.GLFWUtil.*;
import static org.warp.engine.lwjgl.IOUtil.*;
import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL13.*;
import static org.lwjgl.opengl.GL30.*;
import static org.lwjgl.stb.STBTruetype.*;
import static org.lwjgl.system.MemoryUtil.*;
import static org.lwjgl.stb.STBImage.*;
/**
* STB Truetype oversampling demo.
*
* <p>This is a Java port of <a href="https://github.com/nothings/stb/blob/master/tests/oversample/main.c">https://github
* .com/nothings/stb/blob/master/tests/oversample/main.c</a>.</p>
*/
public final class Display {
private static final int BITMAP_W = 5*128;
private static final int BITMAP_H = 9*256;
private static final float[] scale = {
30.0f,
15.0f
};
// ----
private final STBTTAlignedQuad q = STBTTAlignedQuad.malloc();
private final FloatBuffer xb = memAllocFloat(1);
private final FloatBuffer yb = memAllocFloat(1);
private long window;
// ----
private int ww = 480;
private int wh = 320;
private int fbw = ww;
private int fbh = wh;
private int font_tex;
private int skin_tex;
private int skin_w;
private int skin_h;
private int skin_comp;
private ByteBuffer skin;
private STBTTPackedchar.Buffer chardata;
private boolean black_on_white;
private boolean integer_align;
private boolean translating;
private boolean rotating;
private boolean supportsSRGB;
private boolean srgb;
private float rotate_t, translate_t;
private boolean show_tex;
private int font = 0;
private final int maxCharIndex = 9500;
private float[] background = new float[]{0f,0f,0f};
public boolean loading = true;
public String error = null;
public String[] errorStackTrace = null;
public final int[] glyphsHeight = new int[]{9, 6};
public float translation = 0.0f;
public boolean translation_top_to_bottom = true;
public static float brightness = 1.0f;
private Screen screen;
public Display(Screen screen, int ww, int wh) {
this.ww = ww;
this.wh = wh;
setScreen(screen);
}
/*
private void load_skin() {
try {
skin_tex = glGenTextures();
glBindTexture(GL_TEXTURE_2D, skin_tex);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
InputStream in = new FileInputStream("res/skin.png");
PNGDecoder decoder = new PNGDecoder(in);
System.out.println("width="+decoder.getWidth());
System.out.println("height="+decoder.getHeight());
ByteBuffer buf = ByteBuffer.allocateDirect(4*decoder.getWidth()*decoder.getHeight());
decoder.decode(buf, decoder.getWidth()*4, Format.RGBA);
buf.flip();
skin = buf;
skin_w = decoder.getWidth();
skin_h = decoder.getHeight();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, skin_w,
skin_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, skin);
} catch (IOException ex) {
ex.printStackTrace();
}
}*/
private void setScreen(Screen screen) {
if (screen.initialized == false) {
if (screen.canBeInHistory) {
Calculator.currentSession = 0;
for (int i = 1; i < Calculator.sessions.length; i++) {
Calculator.sessions[i] = Calculator.sessions[i-1];
}
Calculator.sessions[0] = this.screen;
}
}
screen.d = this;
try {
screen.initialize();
this.screen = screen;
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean canGoBack() {
if (this.screen != Calculator.sessions[Calculator.currentSession]) {
} else if (Calculator.currentSession+1 < Calculator.sessions.length) {
if (Calculator.sessions[Calculator.currentSession + 1] != null) {
} else {
return false;
}
} else {
return false;
}
if (Calculator.sessions[Calculator.currentSession] != null) {
return true;
}
return false;
}
private void goBack() {
if (canGoBack()) {
if (this.screen != Calculator.sessions[Calculator.currentSession]) {
} else {
Calculator.currentSession += 1;
}
this.screen = Calculator.sessions[Calculator.currentSession];
}
}
private boolean canGoForward() {
if (this.screen != Calculator.sessions[Calculator.currentSession]) {
} else if (Calculator.currentSession > 0) {
if (Calculator.sessions[Calculator.currentSession - 1] != null) {
} else {
return false;
}
} else {
return false;
}
if (Calculator.sessions[Calculator.currentSession] != null) {
return true;
}
return false;
}
private void goForward() {
if (canGoForward()) {
if (this.screen != Calculator.sessions[Calculator.currentSession]) {
} else {
Calculator.currentSession -= 1;
}
this.screen = Calculator.sessions[Calculator.currentSession];
}
}
private Screen getScreen() {
return this.screen;
}
private void load_skin() {
ByteBuffer imageBuffer;
try {
imageBuffer = ioResourceToByteBuffer("skin.png", 8 * 1024);
} catch (IOException e) {
throw new RuntimeException(e);
}
skin_tex = glGenTextures();
glBindTexture(GL_TEXTURE_2D, skin_tex);
IntBuffer w = BufferUtils.createIntBuffer(1);
IntBuffer h = BufferUtils.createIntBuffer(1);
IntBuffer comp = BufferUtils.createIntBuffer(1);
skin = stbi_load_from_memory(imageBuffer, w, h, comp, 0);
if ( skin == null )
throw new RuntimeException("Failed to load image: " + stbi_failure_reason());
skin_w = w.get(0);
skin_h = h.get(0);
skin_comp = comp.get(0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
if ( skin_comp == 3 ) {
if ( (skin_w & 3) != 0 )
glPixelStorei(GL_UNPACK_ALIGNMENT, 2 - (skin_w & 1));
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, skin_w, skin_h, 0, GL_RGB, GL_UNSIGNED_BYTE, skin);
} else {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, skin_w, skin_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, skin);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
glBindTexture(GL_TEXTURE_2D, 0);
stbi_image_free(skin);
}
private void load_fonts() {
font_tex = glGenTextures();
chardata = STBTTPackedchar.mallocBuffer(6*maxCharIndex);
glBindTexture(GL_TEXTURE_2D, font_tex);
try {
STBTTPackContext pc = STBTTPackContext.malloc();
ByteBuffer ttfBig = ioResourceToByteBuffer("font_big.ttf", 18000);
ByteBuffer ttfSmall = ioResourceToByteBuffer("font_small.ttf", 18000);
ByteBuffer bitmap = BufferUtils.createByteBuffer(BITMAP_W * BITMAP_H);
stbtt_PackBegin(pc, bitmap, BITMAP_W, BITMAP_H, 0, 1, null);
chardata.limit(maxCharIndex);
chardata.position(0);
stbtt_PackSetOversampling(pc, 1, 1);
stbtt_PackFontRange(pc, ttfBig, 0, 15 /* Font size */, 0, chardata);
chardata.clear();
chardata.limit(maxCharIndex*2);
chardata.position(maxCharIndex);
stbtt_PackSetOversampling(pc, 1, 1);
stbtt_PackFontRange(pc, ttfSmall, 0, 15 /* Font size */, 0, chardata);
chardata.clear();
stbtt_PackEnd(pc);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, BITMAP_W, BITMAP_H, 0, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private void draw_init() {
glDisable(GL_CULL_FACE);
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glViewport(0, 0, fbw, fbh);
clearColor(background[0], background[1], background[2], 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, ww, wh, 0.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
private static void drawBoxTC(float x0, float y0, float x1, float y1, float s0, float t0, float s1, float t1) {
glTexCoord2f(s0, t0);
glVertex2f(x0, y0);
glTexCoord2f(s1, t0);
glVertex2f(x1, y0);
glTexCoord2f(s1, t1);
glVertex2f(x1, y1);
glTexCoord2f(s0, t1);
glVertex2f(x0, y1);
}
private void print(float x, float y, int font, String text) {
xb.put(0, x);
yb.put(0, y+glyphsHeight[font]);
chardata.position(font * maxCharIndex);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, font_tex);
glBegin(GL_QUADS);
for ( int i = 0; i < text.length(); i++ ) {
stbtt_GetPackedQuad(chardata, BITMAP_W, BITMAP_H, text.charAt(i), xb, yb, q, (font == 0 && integer_align)?1:0);
drawBoxTC(
q.x0(), q.y0(), q.x1(), q.y1(),
q.s0(), q.t0(), q.s1(), q.t1()
);
}
glEnd();
glDisable( GL_TEXTURE_2D );
}
private int[] textSize(int font, String text) {
float[] size = new float[]{0,0};
xb.put(0, 0);
yb.put(0, 0);
chardata.position(font * maxCharIndex);
for ( int i = 0; i < text.length(); i++ ) {
stbtt_GetPackedQuad(chardata, BITMAP_W, BITMAP_H, text.charAt(i), xb, yb, q, (font == 0 && integer_align)?1:0);
size[0]=q.x1();
size[1]=q.y1();
}
return new int[]{(int) size[0], (int) size[1]};
}
private void drawSkinPart(int[] posOnScreen, float[] posOnSkin) {
glEnable(GL_TEXTURE_2D);
colore(1, 1, 1, 1);
glBindTexture(GL_TEXTURE_2D, skin_tex);
glBegin(GL_QUADS);
drawBoxTC(posOnScreen[0],posOnScreen[1],posOnScreen[2], posOnScreen[3], posOnSkin[0]/1000, posOnSkin[1]/100, posOnSkin[2]/1000, posOnSkin[3]/100);
glEnd();
glDisable( GL_TEXTURE_2D );
}
private void drawLine(int[]... pos) {
glLineWidth(1.0f);
glBegin(GL_LINE_STRIP);
for (int[] single_pos : pos) {
glVertex2d(single_pos[0], single_pos[1]);
glVertex2d(single_pos[2], single_pos[3]);
}
glEnd();
}
private void drawRect(int[]... pos) {
glLineWidth(1.0f);
glBegin(GL_QUADS);
for (int[] single_pos : pos) {
glVertex2d(single_pos[0], single_pos[1]);
glVertex2d(single_pos[2], single_pos[1]);
glVertex2d(single_pos[2], single_pos[3]);
glVertex2d(single_pos[0], single_pos[3]);
}
glEnd();
}
private void draw_status() {
colore(background[0],background[1],background[2]);
drawRect(new int[]{0,0,ww,20});
colore(0,0,0);
drawLine(new int[]{0,20,ww,20});
colore(0,0,0);
if (Keyboard.shift) {
drawSkinPart(new int[]{2+18*0,2,2+16+18*0,2+16}, new float[]{16*2,16*0,16+16*2,16+16*0});
} else {
drawSkinPart(new int[]{2+18*0,2,2+16+18*0,2+16}, new float[]{16*3,16*0,16+16*3,16+16*0});
}
if (Keyboard.alpha) {
drawSkinPart(new int[]{2+18*1,2,2+16+18*1,2+16}, new float[]{16*0,16*0,16+16*0,16+16*0});
} else {
drawSkinPart(new int[]{2+18*1,2,2+16+18*1,2+16}, new float[]{16*1,16*0,16+16*1,16+16*0});
}
if (Calculator.angleMode == "deg") {
drawSkinPart(new int[]{8+18*2,2,8+16+18*2,2+16}, new float[]{16*4,16*0,16+16*4,16+16*0});
drawSkinPart(new int[]{8+18*3,2,8+16+18*3,2+16}, new float[]{16*7,16*0,16+16*7,16+16*0});
drawSkinPart(new int[]{8+18*4,2,8+16+18*4,2+16}, new float[]{16*9,16*0,16+16*9,16+16*0});
} else if (Calculator.angleMode == "rad") {
drawSkinPart(new int[]{8+18*2,2,8+16+18*2,2+16}, new float[]{16*5,16*0,16+16*5,16+16*0});
drawSkinPart(new int[]{8+18*3,2,8+16+18*3,2+16}, new float[]{16*6,16*0,16+16*6,16+16*0});
drawSkinPart(new int[]{8+18*4,2,8+16+18*4,2+16}, new float[]{16*9,16*0,16+16*9,16+16*0});
} else if (Calculator.angleMode == "gra") {
drawSkinPart(new int[]{8+18*2,2,8+16+18*2,2+16}, new float[]{16*5,16*0,16+16*5,16+16*0});
drawSkinPart(new int[]{8+18*3,2,8+16+18*3,2+16}, new float[]{16*7,16*0,16+16*7,16+16*0});
drawSkinPart(new int[]{8+18*4,2,8+16+18*4,2+16}, new float[]{16*8,16*0,16+16*8,16+16*0});
} else {
drawSkinPart(new int[]{8+18*2,2,8+16+18*2,2+16}, new float[]{16*5,16*0,16+16*5,16+16*0});
drawSkinPart(new int[]{8+18*3,2,8+16+18*3,2+16}, new float[]{16*7,16*0,16+16*7,16+16*0});
drawSkinPart(new int[]{8+18*4,2,8+16+18*4,2+16}, new float[]{16*9,16*0,16+16*9,16+16*0});
}
int padding = 2;
int brightness = (int)(Display.brightness * 4);
if (brightness == 1) {
drawSkinPart(new int[]{ww-(padding+18*0),2,ww-(padding+16+18*0),2+16}, new float[]{16*10,16*0,16+16*10,16+16*0});
} else if (brightness == 2) {
drawSkinPart(new int[]{ww-(padding+18*0),2,ww-(padding+16+18*0),2+16}, new float[]{16*11,16*0,16+16*11,16+16*0});
} else if (brightness == 3) {
drawSkinPart(new int[]{ww-(padding+18*0),2,ww-(padding+16+18*0),2+16}, new float[]{16*12,16*0,16+16*12,16+16*0});
} else if (brightness == 4) {
drawSkinPart(new int[]{ww-(padding+18*0),2,ww-(padding+16+18*0),2+16}, new float[]{16*13,16*0,16+16*13,16+16*0});
}
padding += 18+6;
boolean canGoBack = canGoBack();
boolean canGoForward = canGoForward();
if (Calculator.haxMode) {
drawSkinPart(new int[]{ww-(padding+16),2,ww-padding,2+16}, new float[]{16*18,16*0,16+16*18,16+16*0});
padding += 18+6;
}
if (canGoBack && canGoForward) {
drawSkinPart(new int[]{ww-(padding+16),2,ww-padding,2+16}, new float[]{16*14,16*0,16+16*14,16+16*0});
} else if (canGoBack) {
drawSkinPart(new int[]{ww-(padding+16),2,ww-padding,2+16}, new float[]{16*15,16*0,16+16*15,16+16*0});
} else if (canGoForward) {
drawSkinPart(new int[]{ww-(padding+16),2,ww-padding,2+16}, new float[]{16*16,16*0,16+16*16,16+16*0});
} else {
drawSkinPart(new int[]{ww-(padding+16),2,ww-padding,2+16}, new float[]{16*17,16*0,16+16*17,16+16*0});
}
padding += 18;
}
private void draw_screen() {
screen.render();
}
private void draw_bottom() {
}
private void draw_world() {
float x = 20;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
colore(1.0f, 1.0f, 1.0f);
if (error != null) {
colore(0.0f, 0.0f, 0.0f, 0.75f);
print(ww-textSize(1, "ANDREA CAVALLI'S CALCULATOR")[0]-2, wh-this.glyphsHeight[1]-2, 1, "ANDREA CAVALLI'S CALCULATOR");
colore(0.0f, 0.0f, 0.0f, 0.75f);
print((ww/2)-(textSize(0, "UNEXPECTED EXCEPTION")[0]/2), 11, 0, "UNEXPECTED EXCEPTION");
colore(0.0f, 0.0f, 0.0f, 0.5f);
print((ww/2)-(textSize(1, error)[0]/2), 22, 1, error);
colore(0.0f, 0.0f, 0.0f, 0.4f);
int i = 22;
for (String stackPart : errorStackTrace) {
print(2, 22+i, 1, stackPart);
i+=11;
}
} else if (loading) {
colore(1.0f, 1.0f, 1.0f, 1.0f);
int titlew = textSize(0, "ANDREA CAVALLI'S CALCULATOR")[0];
print((ww/2)-(titlew/2)-1, (wh/2)-25+translation, 0, "ANDREA CAVALLI'S CALCULATOR");
colore(1.0f, 1.0f, 1.0f, 1.0f);
print((ww/2)-(titlew/2)+1, (wh/2)-25+translation, 0, "ANDREA CAVALLI'S CALCULATOR");
colore(1.0f, 1.0f, 1.0f, 1.0f);
print((ww/2)-(titlew/2), (wh/2)-25-1+translation, 0, "ANDREA CAVALLI'S CALCULATOR");
colore(1.0f, 1.0f, 1.0f, 1.0f);
print((ww/2)-(titlew/2), (wh/2)-25+1+translation, 0, "ANDREA CAVALLI'S CALCULATOR");
colore(1.0f, 0.5f, 0.0f, 1.0f);
print((ww/2)-(titlew/2), (wh/2)-25+translation, 0, "ANDREA CAVALLI'S CALCULATOR");
colore(0.0f, 0.0f, 0.0f, 0.75f);
print((ww/2)-(textSize(0, "LOADING")[0]/2), (wh/2)+11, 0, "LOADING");
colore(0.0f, 0.0f, 0.0f, 0.5f);
print((ww/2)-(textSize(1, "PLEASE WAIT...")[0]/2), (wh/2)+22, 1, "PLEASE WAIT...");
} else {
draw_status();
draw_screen();
draw_bottom();
}
}
private void draw() {
draw_init();
draw_world();
glfwSwapBuffers(window);
}
private void loopmode(float dt) {
rotate_t += dt;
translate_t += dt;
/*
* Calcoli
*/
if (translation >= 10.0f) {
translation = 10.0f;
translation_top_to_bottom = false;
} else if (translation <= -10.0f) {
translation = -10.0f;
translation_top_to_bottom = true;
}
if (translation_top_to_bottom) {
translation += dt*15;
} else {
translation -= dt*15;
}
screen.beforeRender(dt);
draw();
}
private GLFWKeyCallback keyCallback = new GLFWKeyCallback() {
@Override
public void invoke(long window, int key, int scancode, int action, int mods) {
if ( action == GLFW_RELEASE )
return;
switch ( key ) {
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, GLFW_TRUE);
break;
case GLFW_KEY_F:
font = 1;
break;
case GLFW_KEY_R:
rotating = !rotating;
rotate_t = 0.0f;
break;
case GLFW_KEY_P:
integer_align = !integer_align;
break;
case GLFW_KEY_G:
font = 0;
break;
case GLFW_KEY_V:
show_tex = !show_tex;
break;
case GLFW_KEY_B:
black_on_white = !black_on_white;
break;
}
}
};
private GLFWWindowSizeCallback sizecallback = new GLFWWindowSizeCallback() {
@Override
public void invoke(long window, int width, int height) {
Display.this.ww = width;
Display.this.wh = height;
}
};
private GLFWFramebufferSizeCallback fbsizecallback = new GLFWFramebufferSizeCallback() {
@Override
public void invoke(long window, int width, int height) {
Display.this.fbw = width;
Display.this.fbh = height;
}
};
private void createWindow(String title) {
GLFWErrorCallback.createPrint().set();
if ( glfwInit() == GLFW_FALSE )
throw new IllegalStateException("Unable to initialize GLFW");
glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
this.window = glfwCreateWindow(ww, wh, title, NULL, NULL);
if ( window == NULL )
throw new RuntimeException("Failed to create the GLFW window");
glfwSetWindowSizeCallback(window, sizecallback);
glfwSetFramebufferSizeCallback(window, fbsizecallback);
glfwSetKeyCallback(window, keyCallback);
// Center window
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(
window,
(vidmode.width() - ww) / 2,
(vidmode.height() - wh) / 2
);
// Create context
glfwMakeContextCurrent(window);
GL.createCapabilities();
glfwSwapInterval(1);
glfwShowWindow(window);
glfwInvoke(window, sizecallback, fbsizecallback);
// Detect sRGB support
GLCapabilities caps = GL.getCapabilities();
supportsSRGB = caps.OpenGL30 || caps.GL_ARB_framebuffer_sRGB || caps.GL_EXT_framebuffer_sRGB;
}
public void run(String title) {
try {
createWindow(title);
load_skin();
load_fonts();
long time = System.nanoTime();
while ( glfwWindowShouldClose(window) == GLFW_FALSE ) {
glfwPollEvents();
long t = System.nanoTime();
float dt = (float)((t - time) / 1000000000.0);
time = t;
loopmode(dt);
}
} finally {
try {
destroy();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void destroy() {
chardata.clear();
glfwTerminate();
glfwSetErrorCallback(null);
memFree(yb);
memFree(xb);
q.free();
}
public void setBackground(float d, float e, float f) {
background = new float[]{d,e,f};
}
public void colore(float f1, float f2, float f3) {
glColor3f(f1*brightness, f2*brightness, f3*brightness);
}
public void colore(float f1, float f2, float f3, float f4) {
glColor4f(f1*brightness, f2*brightness, f3*brightness, f4);
}
public void clearColor(float f1, float f2, float f3, float f4) {
glClearColor(f1*brightness,f2*brightness,f3*brightness,f4);
}
}

View File

@ -0,0 +1,47 @@
package org.warp.engine.lwjgl;
import org.lwjgl.glfw.GLFWFramebufferSizeCallbackI;
import org.lwjgl.glfw.GLFWWindowSizeCallbackI;
import org.lwjgl.system.MemoryStack;
import java.nio.IntBuffer;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.system.MemoryStack.*;
/** GLFW demo utilities. */
public final class GLFWUtil {
private GLFWUtil() {
}
/**
* Invokes the specified callbacks using the current window and framebuffer sizes of the specified GLFW window.
*
* @param window the GLFW window
* @param windowSizeCB the window size callback, may be null
* @param framebufferSizeCB the framebuffer size callback, may be null
*/
public static void glfwInvoke(
long window,
GLFWWindowSizeCallbackI windowSizeCB,
GLFWFramebufferSizeCallbackI framebufferSizeCB
) {
try ( MemoryStack stack = stackPush() ) {
IntBuffer w = stack.mallocInt(1);
IntBuffer h = stack.mallocInt(1);
if ( windowSizeCB != null ) {
glfwGetWindowSize(window, w, h);
windowSizeCB.invoke(window, w.get(0), h.get(0));
}
if ( framebufferSizeCB != null ) {
glfwGetFramebufferSize(window, w, h);
framebufferSizeCB.invoke(window, w.get(0), h.get(0));
}
}
}
}

View File

@ -0,0 +1,69 @@
package org.warp.engine.lwjgl;
import org.lwjgl.BufferUtils;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import static org.lwjgl.BufferUtils.*;
public final class IOUtil {
private IOUtil() {
}
private static ByteBuffer resizeBuffer(ByteBuffer buffer, int newCapacity) {
ByteBuffer newBuffer = BufferUtils.createByteBuffer(newCapacity);
buffer.flip();
newBuffer.put(buffer);
return newBuffer;
}
/**
* Reads the specified resource and returns the raw data as a ByteBuffer.
*
* @param resource the resource to read
* @param bufferSize the initial buffer size
*
* @return the resource data
*
* @throws IOException if an IO error occurs
*/
public static ByteBuffer ioResourceToByteBuffer(String resource, int bufferSize) throws IOException {
ByteBuffer buffer;
Path path = Paths.get(resource);
if ( Files.isReadable(path) ) {
try (SeekableByteChannel fc = Files.newByteChannel(path)) {
buffer = BufferUtils.createByteBuffer((int)fc.size() + 1);
while ( fc.read(buffer) != -1 ) ;
}
} else {
try (
InputStream source = IOUtil.class.getClassLoader().getResourceAsStream(resource);
ReadableByteChannel rbc = Channels.newChannel(source)
) {
buffer = createByteBuffer(bufferSize);
while ( true ) {
int bytes = rbc.read(buffer);
if ( bytes == -1 )
break;
if ( buffer.remaining() == 0 )
buffer = resizeBuffer(buffer, buffer.capacity() * 2);
}
}
}
buffer.flip();
return buffer;
}
}

View File

@ -0,0 +1,23 @@
package org.warp.engine.lwjgl;
public abstract class Screen {
public Display d;
public boolean initialized = false;
public boolean canBeInHistory = false;
public Screen() {
}
public void initialize() throws InterruptedException {
if (!initialized) {
initialized = true;
init();
}
}
public abstract void init() throws InterruptedException;
public abstract void render();
public abstract void beforeRender(float dt);
}

View File

@ -0,0 +1,212 @@
package org.warpgate.pi.calculator;
import java.awt.*;
import java.io.*;
import java.awt.image.*;
public class BMPFile extends Component {
//--- Private constants
private final static int BITMAPFILEHEADER_SIZE = 14;
private final static int BITMAPINFOHEADER_SIZE = 40;
//--- Private variable declaration
//--- Bitmap file header
private byte bitmapFileHeader [] = new byte [14];
private byte bfType [] = {'B', 'M'};
private int bfSize = 0;
private int bfReserved1 = 0;
private int bfReserved2 = 0;
private int bfOffBits = BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE;
//--- Bitmap info header
private byte bitmapInfoHeader [] = new byte [40];
private int biSize = BITMAPINFOHEADER_SIZE;
private int biWidth = 0;
private int biHeight = 0;
private int biPlanes = 1;
private int biBitCount = 24;
private int biCompression = 0;
private int biSizeImage = 0x030000;
private int biXPelsPerMeter = 0x0;
private int biYPelsPerMeter = 0x0;
private int biClrUsed = 0;
private int biClrImportant = 0;
//--- Bitmap raw data
private int bitmap [];
//--- File section
private FileOutputStream fo;
//--- Default constructor
public BMPFile() {
}
public void saveBitmap (String parFilename, Image parImage, int
parWidth, int parHeight) {
try {
fo = new FileOutputStream (parFilename);
save (parImage, parWidth, parHeight);
fo.close ();
}
catch (Exception saveEx) {
saveEx.printStackTrace ();
}
}
/*
* The saveMethod is the main method of the process. This method
* will call the convertImage method to convert the memory image to
* a byte array; method writeBitmapFileHeader creates and writes
* the bitmap file header; writeBitmapInfoHeader creates the
* information header; and writeBitmap writes the image.
*
*/
private void save (Image parImage, int parWidth, int parHeight) {
try {
convertImage (parImage, parWidth, parHeight);
writeBitmapFileHeader ();
writeBitmapInfoHeader ();
writeBitmap ();
}
catch (Exception saveEx) {
saveEx.printStackTrace ();
}
}
/*
* convertImage converts the memory image to the bitmap format (BRG).
* It also computes some information for the bitmap info header.
*
*/
private boolean convertImage (Image parImage, int parWidth, int parHeight) {
int pad;
bitmap = new int [parWidth * parHeight];
PixelGrabber pg = new PixelGrabber (parImage, 0, 0, parWidth, parHeight,
bitmap, 0, parWidth);
try {
pg.grabPixels ();
}
catch (InterruptedException e) {
e.printStackTrace ();
return (false);
}
pad = (4 - ((parWidth * 3) % 4)) * parHeight;
biSizeImage = ((parWidth * parHeight) * 3) + pad;
bfSize = biSizeImage + BITMAPFILEHEADER_SIZE +
BITMAPINFOHEADER_SIZE;
biWidth = parWidth;
biHeight = parHeight;
return (true);
}
/*
* writeBitmap converts the image returned from the pixel grabber to
* the format required. Remember: scan lines are inverted in
* a bitmap file!
*
* Each scan line must be padded to an even 4-byte boundary.
*/
private void writeBitmap () {
int size;
int value;
int j;
int i;
int rowCount;
int rowIndex;
int lastRowIndex;
int pad;
int padCount;
byte rgb [] = new byte [3];
size = (biWidth * biHeight) - 1;
pad = 4 - ((biWidth * 3) % 4);
if (pad == 4) // <==== Bug correction
pad = 0; // <==== Bug correction
rowCount = 1;
padCount = 0;
rowIndex = size - biWidth;
lastRowIndex = rowIndex;
try {
for (j = 0; j < size; j++) {
value = bitmap [rowIndex];
rgb [0] = (byte) (value & 0xFF);
rgb [1] = (byte) ((value >> 8) & 0xFF);
rgb [2] = (byte) ((value >> 16) & 0xFF);
fo.write (rgb);
if (rowCount == biWidth) {
padCount += pad;
for (i = 1; i <= pad; i++) {
fo.write (0x00);
}
rowCount = 1;
rowIndex = lastRowIndex - biWidth;
lastRowIndex = rowIndex;
}
else
rowCount++;
rowIndex++;
}
//--- Update the size of the file
bfSize += padCount - pad;
biSizeImage += padCount - pad;
}
catch (Exception wb) {
wb.printStackTrace ();
}
}
/*
* writeBitmapFileHeader writes the bitmap file header to the file.
*
*/
private void writeBitmapFileHeader () {
try {
fo.write (bfType);
fo.write (intToDWord (bfSize));
fo.write (intToWord (bfReserved1));
fo.write (intToWord (bfReserved2));
fo.write (intToDWord (bfOffBits));
}
catch (Exception wbfh) {
wbfh.printStackTrace ();
}
}
/*
*
* writeBitmapInfoHeader writes the bitmap information header
* to the file.
*
*/
private void writeBitmapInfoHeader () {
try {
fo.write (intToDWord (biSize));
fo.write (intToDWord (biWidth));
fo.write (intToDWord (biHeight));
fo.write (intToWord (biPlanes));
fo.write (intToWord (biBitCount));
fo.write (intToDWord (biCompression));
fo.write (intToDWord (biSizeImage));
fo.write (intToDWord (biXPelsPerMeter));
fo.write (intToDWord (biYPelsPerMeter));
fo.write (intToDWord (biClrUsed));
fo.write (intToDWord (biClrImportant));
}
catch (Exception wbih) {
wbih.printStackTrace ();
}
}
/*
*
* intToWord converts an int to a word, where the return
* value is stored in a 2-byte array.
*
*/
private byte [] intToWord (int parValue) {
byte retValue [] = new byte [2];
retValue [0] = (byte) (parValue & 0x00FF);
retValue [1] = (byte) ((parValue >> 8) & 0x00FF);
return (retValue);
}
/*
*
* intToDWord converts an int to a double word, where the return
* value is stored in a 4-byte array.
*
*/
private byte [] intToDWord (int parValue) {
byte retValue [] = new byte [4];
retValue [0] = (byte) (parValue & 0x00FF);
retValue [1] = (byte) ((parValue >> 8) & 0x000000FF);
retValue [2] = (byte) ((parValue >> 16) & 0x000000FF);
retValue [3] = (byte) ((parValue >> 24) & 0x000000FF);
return (retValue);
}
}

View File

@ -0,0 +1,46 @@
package org.warpgate.pi.calculator;
import java.util.Vector;
import com.rits.cloning.Cloner;
public class Equazione extends FunzioneDueValori {
public Equazione(Funzione value1, Funzione value2) {
super(value1, value2);
}
@Override
public String simbolo() {
return Simboli.EQUATION;
}
@Override
public Termine calcola() throws Errore {
return new Sottrazione(getVariable1().calcola(),getVariable2().calcola()).calcola();
}
public Vector<Equazione> risolviPassaggio(char charIncognita) {
Vector<Equazione> result = new Vector<Equazione>();
result.add(this.clone());
for (Tecnica t : Tecnica.tecniche) {
Vector<Equazione> newResults = new Vector<Equazione>();
final int sz = result.size();
for (int n = 0; n < sz; n++) {
Vector<Equazione> singleResult = t.risolvi(result.get(n));
final int sz2 = singleResult.size();
for (int n2 = 0; n2 < sz2; n2++) {
}
}
}
//TODO: finire
return result;
}
public Equazione clone() {
Cloner cloner = new Cloner();
return cloner.deepClone(this);
}
}

View File

@ -0,0 +1,42 @@
package org.warpgate.pi.calculator;
import java.math.BigInteger;
import org.nevec.rjm.Rational;
public class Incognita {
public char simbolo = 'X';
public Rational esponente = Rational.ONE;
public Incognita(char simbolo, Rational esponente) {
this.simbolo = simbolo;
this.esponente = esponente;
}
public Incognita(char simbolo, int a, int b) {
this.simbolo = simbolo;
this.esponente = new Rational(a, b);
}
public Incognita(char simbolo) {
this.simbolo = simbolo;
this.esponente = new Rational(1, 1);
}
@Override
public boolean equals(Object o) {
if (o instanceof Incognita) {
if (this.simbolo == ((Incognita) o).simbolo) {
if (this.esponente == ((Incognita) o).esponente) {
return true;
}
}
}
return false;
}
@Override
public int hashCode() {
return Character.getNumericValue(simbolo)*3+esponente.hashCode();
}
}

View File

@ -0,0 +1,388 @@
package org.warpgate.pi.calculator;
import java.math.BigInteger;
import java.text.Collator;
import java.util.Comparator;
import java.util.List;
import java.util.Vector;
import org.nevec.rjm.BigIntegerMath;
import org.nevec.rjm.Rational;
public class Incognite {
Vector<Incognita> incognite;
public Incognite() {
incognite = new Vector<Incognita>();
}
public Incognite(Incognita[] value) {
this();
for (Incognita i : value) {
incognite.add(i);
}
}
public Incognite(Vector<Incognita> value) {
this();
incognite = value;
}
public Incognite(Incognita value) {
this();
incognite.add(value);
}
public int count() {
return incognite.size();
}
public boolean contieneSimbolo(char simbolo) {
for (Incognita i : incognite) {
if (i.simbolo == simbolo) {
return true;
}
}
return false;
}
public Rational prendiEsponenteSimbolo(char simbolo) {
for (Incognita i : incognite) {
if (i.simbolo == simbolo) {
return i.esponente;
}
}
return new Rational(0, 1);
}
public void impostaEsponenteSimbolo(char simbolo, Rational esponente) {
for (Incognita i : incognite) {
if (i.simbolo == simbolo) {
i.esponente = esponente;
}
}
}
@SuppressWarnings("unchecked")
@Override
public Incognite clone() {
return new Incognite((Vector<Incognita>) incognite.clone()).normalize();
}
public Incognite multiply(Incognite val) {
Incognite result = new Incognite();
//Passaggio 1: test vari
//Se il primo gruppo di incognite è nullo allora ritorna il secondo gruppo
if (this.count() == 0) {
result = val.clone();
return result;
}
//Se il secondo gruppo di incognite è nullo allora ritorna il primo gruppo
if (val.count() == 0) {
result = this.clone();
return result;
}
//Passaggio 2: le incognite doppie vengono raggruppate.
for (Incognita i1 : incognite) {
for (Incognita i2 : val.incognite) {
if (i1.simbolo == i2.simbolo) {
if (!result.contieneSimbolo(i1.simbolo)) {
Incognita ir = new Incognita(i1.simbolo, i1.esponente.add(i2.esponente));
result.incognite.add(ir);
}
}
}
}
//Passaggio 3: le incognite non ancora presenti vengono aggiunte.
for (Incognita i : incognite) {
if (!result.contieneSimbolo(i.simbolo)) {
result.incognite.add(i);
}
}
for (Incognita i : val.incognite) {
if (!result.contieneSimbolo(i.simbolo)) {
result.incognite.add(i);
}
}
return result.normalize();
}
public Incognite divide(Incognite val) {
Incognite result = new Incognite();
//Passaggio 2: le incognite doppie vengono raggruppate.
for (Incognita i1 : incognite) {
for (Incognita i2 : val.incognite) {
if (i1.simbolo == i2.simbolo) {
if (!result.contieneSimbolo(i1.simbolo)) {
Incognita ir = new Incognita(i1.simbolo, i1.esponente.add(i2.esponente.multiply(new Rational(-1, 1))));
result.incognite.add(ir);
}
}
}
}
//Passaggio 3: le incognite non ancora presenti vengono aggiunte.
for (Incognita i : incognite) {
if (!result.contieneSimbolo(i.simbolo)) {
result.incognite.add(i);
}
}
for (Incognita i : val.incognite) {
if (!result.contieneSimbolo(i.simbolo)) {
result.incognite.add(new Incognita(i.simbolo, i.esponente.multiply(new Rational(-1, 1))));
}
}
return result.normalize();
}
public Incognite sqrt() {
Incognite result = new Incognite();
for (Incognita i1 : incognite) {
Incognita ir = null;
try {
ir = new Incognita(i1.simbolo, i1.esponente.divide(new Rational(2, 1)));
} catch (Errore e) {
e.printStackTrace();
}
result.incognite.add(ir);
}
return result.normalize();
}
public Incognite normalize() {
Incognite result = new Incognite();
for (Incognita i1 : incognite) {
if (i1.esponente.compareTo(Rational.ZERO) != 0) {
result.incognite.add(i1);
}
}
result.incognite.sort(new Comparator<Incognita>() {
@Override
public int compare(Incognita o1, Incognita o2) {
int index1 = letterIndex(o1.simbolo);
int index2 = letterIndex(o2.simbolo);
return index1-index2;
}
});
return result;
}
public byte letterIndex(char l) {
return letterIndex(l, false);
}
public static byte letterIndex(char l, boolean reverse) {
int total = Simboli.incognite().length-1;
for (byte x = 0; x < Simboli.incognite().length; x++) {
if (Simboli.incognite()[x].equals(""+l)) {
if (reverse) {
return (byte) (total-x);
} else {
return x;
}
}
}
return -1;
}
public boolean compareTo(Incognite val) {
if (this.equals(val)) return true;
return false;
}
@Override
public boolean equals(Object val) {
if (val == null) return false;
if (val instanceof Incognite) {
Incognite ii2 = (Incognite) val;
for (Incognita i1 : incognite) {
boolean found = false;
for (Incognita i2 : ii2.incognite) {
if (i1.simbolo == i2.simbolo) {
if (i1.esponente.compareTo(i2.esponente) != 0)
return false;
found = true;
}
}
if (!found) {
return false;
}
}
for (Incognita i1 : ii2.incognite) {
boolean found = false;
for (Incognita i2 : incognite) {
if (i1.simbolo == i2.simbolo) {
if (i1.esponente.compareTo(i2.esponente) != 0)
return false;
found = true;
}
}
if (!found) {
return false;
}
}
return true;
}
return false;
}
@Override
public String toString() {
String result = "";
if (incognite.size() != 1) {
for (Incognita i : incognite) {
if (i.esponente.compareTo(Rational.ONE) != 0) {
result += "("+i.simbolo+"^"+i.esponente+")";
} else {
result += i.simbolo;
}
}
} else if (incognite.size() == 1) {
Incognita i = incognite.get(0);
if (i.esponente.compareTo(Rational.ONE) != 0) {
result += ""+i.simbolo+"^"+i.esponente+"";
} else if (i.esponente.compareTo(Rational.ONE) == 0) {
result += i.simbolo;
}
}
return result;
}
public static Incognite lcm(Incognite val1, Incognite val2) {
Incognite result = new Incognite();
//Passaggio 1: test vari
//Se il primo gruppo di incognite è nullo allora ritorna il secondo gruppo
if (val1.count() == 0) {
result = val2.clone();
return result;
}
//Se il secondo gruppo di incognite è nullo allora ritorna il primo gruppo
if (val2.count() == 0) {
result = val1.clone();
return result;
}
//Passaggio 2: le incognite doppie vengono raggruppate.
for (Incognita i1 : val1.incognite) {
for (Incognita i2 : val2.incognite) {
if (i1.simbolo == i2.simbolo) {
if (!result.contieneSimbolo(i1.simbolo)) {
Incognita ir = new Incognita(i1.simbolo);
if (i1.esponente.compareTo(i2.esponente) > 0) {
ir.esponente = i1.esponente;
} else {
ir.esponente = i2.esponente;
}
result.incognite.add(ir);
}
}
}
}
//Passaggio 3: le incognite non ancora presenti vengono aggiunte.
for (Incognita i : val1.incognite) {
if (!result.contieneSimbolo(i.simbolo)) {
result.incognite.add(i);
}
}
for (Incognita i : val2.incognite) {
if (!result.contieneSimbolo(i.simbolo)) {
result.incognite.add(i);
}
}
return result.normalize();
}
@SuppressWarnings("unchecked")
public Vector<Incognita> listaIncognite() {
return (Vector<Incognita>) this.incognite.clone();
}
public static Incognite[] normalizeBigSurdVariables(Incognite[] incognitetemp) throws Errore {
Incognite incognitex = incognitetemp[0].clone();
Incognite incognitey = incognitetemp[1].clone();
Incognite incognitez = incognitetemp[2].clone();
Incognite newincognitex = new Incognite();
for (Incognita i : incognitex.incognite) {
Vector<BigInteger> divisori = BigIntegerMath.divisors(i.esponente.divide(2).denom());
if (divisori.contains(new BigInteger("2"))) {
newincognitex = newincognitex.multiply(new Incognite(i));
} else {
incognitey = incognitey.multiply(new Incognite(new Incognita(i.simbolo, i.esponente.divide(2))));
}
}
incognitex = newincognitex;
for (Incognita i : incognitey.incognite) {
if (i.esponente.signum() < 0) {
incognitey = incognitey.divide(new Incognite(i));
incognitez = incognitez.divide(new Incognite(i));
}
}
for (Incognita i : incognitez.incognite) {
if (i.esponente.signum() < 0) {
incognitey = incognitey.divide(new Incognite(i));
incognitez = incognitez.divide(new Incognite(i));
}
}
//TODO: SPOSTARE LE Y NEGATIVE SOTTO LA FRAZIONE, DALLA Y ALLA Z
Incognite incogniteyresult = new Incognite();
Incognite incognitezresult = new Incognite();
//Le incognite doppie vengono tolte
for (Incognita i1 : incognitey.incognite) {
for (Incognita i2 : incognitez.incognite) {
if (i1.simbolo == i2.simbolo) {
if (i1.esponente.compareTo(i2.esponente) > 0) {
incogniteyresult = incogniteyresult.multiply(new Incognite(new Incognita(i1.simbolo, i1.esponente.subtract(i2.esponente))));
} else if (i2.esponente.compareTo(i1.esponente) > 0) {
incognitezresult = incognitezresult.multiply(new Incognite(new Incognita(i1.simbolo, i2.esponente.subtract(i1.esponente))));
}
}
}
}
//Le altre incognite vengono ri-messe
for (Incognita i : incognitey.incognite) {
if (!incogniteyresult.contieneSimbolo(i.simbolo)) {
incogniteyresult = incogniteyresult.multiply(new Incognite(i));
}
}
for (Incognita i : incognitez.incognite) {
if (!incognitezresult.contieneSimbolo(i.simbolo)) {
incognitezresult = incognitezresult.multiply(new Incognite(i));
}
}
incognitey = incogniteyresult;
incognitez = incognitezresult;
return new Incognite[]{incognitex, incognitey, incognitez};
}
public static int priorità(Incognite ii) {
double priorità = 0;
double letterMax = 0;
for(Incognita i : ii.incognite) {
int lettIndex = letterIndex(i.simbolo, true);
if (lettIndex > letterMax) {
letterMax = lettIndex;
}
}
priorità+=letterMax*100000;
for(Incognita i : ii.incognite) {
int lettIndex = letterIndex(i.simbolo, true);
if (letterMax == lettIndex) {
priorità+=i.esponente.doubleValue()*100000;
}
priorità+=+i.esponente.doubleValue();
}
return (int) priorità;
}
}

View File

@ -0,0 +1,6 @@
package org.warpgate.pi.calculator;
public class Keyboard {
public static boolean alpha = false;
public static boolean shift = false;
}

View File

@ -0,0 +1,63 @@
package org.warpgate.pi.calculator;
import java.awt.Color;
import org.nevec.rjm.Rational;
import org.warp.engine.Display;
public class ParteSistema extends FunzioneAnteriore {
public ParteSistema(Funzione value) {
super(value);
}
@Override
public String simbolo() {
return Simboli.SYSTEM;
}
@Override
public Termine calcola() throws NumberFormatException, Errore {
//TODO implementare il calcolo dei sistemi
return variable.calcola();
}
@Override
public void draw(int x, int y, Display g, boolean small) {
small = false;
final int h = this.getHeight(small)-1;
final int varLine = variable.getLine(small);
final int paddingTop = 3;
final int spazioSotto = (h-3-2)/2+paddingTop;
final int spazioSopra = h - spazioSotto;
variable.draw(x+5, y+paddingTop, g, small);
g.setColor(Color.black);
g.drawOrthoLine(x+2, y+0, x+3, y+0);
g.drawOrthoLine(x+1, y+1, x+1, y+spazioSotto/2);
g.drawOrthoLine(x+2, y+spazioSotto/2+1, x+2, y+spazioSotto-1);
g.drawOrthoLine(x+0, y+spazioSotto, x+1, y+spazioSotto);
g.drawOrthoLine(x+2, y+spazioSotto+1, x+2, y+spazioSotto+spazioSopra/2-1);
g.drawOrthoLine(x+1, y+spazioSotto+spazioSopra/2, x+1, y+h-1);
g.drawOrthoLine(x+2, y+h, x+3, y+h);
}
@Override
public int getWidth() {
return 5+getVariable().getWidth();
}
@Override
public int getHeight(boolean small) {
small = false;
int h1 = 3+getVariable().getHeight(small)+2;
return h1;
}
@Override
public int getLine(boolean small) {
small = false;
int h1 = 3+getVariable().getLine(small);
return h1;
}
}

View File

@ -0,0 +1,22 @@
package org.warpgate.pi.calculator;
import java.awt.Color;
import java.awt.Graphics;
public class Sottrazione extends FunzioneDueValori {
public Sottrazione(Funzione value1, Funzione value2) {
super(value1, value2);
}
@Override
public String simbolo() {
return Simboli.SUBTRACTION;
}
@Override
public Termine calcola() throws Errore {
return getVariable1().calcola().add(getVariable2().calcola().multiply(new Termine("-1")));
}
}

View File

@ -0,0 +1,9 @@
package org.warpgate.pi.calculator;
import java.util.Vector;
public interface Tecnica {
public static final Tecnica[] tecniche = new Tecnica[] {};
public abstract Vector<Equazione> risolvi(Equazione equazione);
}

View File

@ -0,0 +1,29 @@
package org.warpgate.pi.calculator.screens;
import org.warp.engine.lwjgl.Screen;
public class EmptyScreen extends Screen {
public float endLoading;
@Override
public void init() throws InterruptedException {
canBeInHistory = true;
endLoading = 0;
}
@Override
public void render() {
// TODO Auto-generated method stub
}
@Override
public void beforeRender(float dt) {
endLoading += dt;
if (d.loading & endLoading >= 2.5) {
d.loading = false;
}
}
}

View File

@ -0,0 +1,203 @@
package org.warpgate.pi.calculator.screens;
import java.awt.Color;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.warp.engine.lwjgl.Screen;
import org.warpgate.pi.calculator.Calculator;
import org.warpgate.pi.calculator.Errore;
import org.warpgate.pi.calculator.Errori;
import org.warpgate.pi.calculator.Funzione;
import org.warpgate.pi.calculator.Main;
import org.warpgate.pi.calculator.Parentesi;
import org.warpgate.pi.calculator.RisultatoEquazione;
import org.warpgate.pi.calculator.Termine;
public class EquationScreen extends Screen {
public float endLoading;
public static volatile String equazione = "";
public static Parentesi f;
public static Funzione f2;
public static int ew1;
public static int ew2;
public static int eh2;
public static int x1;
public static int x2;
public static boolean requiresleep1;
public static boolean requiresleep2;
public static boolean aftersleep;
public static boolean autoscroll;
@Override
public void init() throws InterruptedException {
canBeInHistory = true;
endLoading = 0;
try {
/* Fine caricamento */
//Parentesi f = new Parentesi("(Ⓐ(2X)*3Y)/(5Z^2)+(Ⓐ(11A)*13B)/(7CZ)=19XZ");
//PARENTESI CON CALCOLI
//Funzione f = new Sottrazione(new Somma(new Parentesi("Ⓐ9/2+Ⓐ7/2", "").calcola(), new Termine("3.5")), new Parentesi("3*2√14","").calcola());
//PARENTESI CON DUE NUMERI FRAZIONALI COMPLETI CON INCOGNITE:
//Funzione f = new Parentesi("(Ⓐ(2X)*3Y)/(5Z^2)+(Ⓐ(11A)*13B)/(7CZ)", "");
//PARENTESI CON DUE NUMERI FRAZIONALI DISALLINEATI GRAFICAMENTE:
//Funzione f = new Parentesi("((5^2-1)/2)/5-5/(5/2)=2", "");
//TERMINE DI PROVA COMPLETO:
//Funzione f = new Termine(new NumeroAvanzato(new Rational(3, 2), new Rational(7, 1), new Incognite(new Incognita('X', Rational.ONE)), new Incognite(new Incognita('Y', Rational.ONE)), new Incognite(new Incognita('z', Rational.ONE))));
//PARENTESI REALISTICA CON INCOGNITE:
//Funzione f = new Equazione(new Parentesi("X^2+(MX-M+4)^2-4X-4(MX-M+4)^2+7", ""), new Termine("0"));
//POTENZA:
//Funzione f = new Parentesi("(MX-M+4)^2", "");
//NUMERO SEMPLICE LUNGO:
//Funzione f = new Parentesi("-1219999799999996934.42229", "");
//:
//Funzione f = new Parentesi("5Y+XY=2", "")
equazione = "0";
f = new Parentesi(equazione);
f2 = f.calcolaSistema();
ew1 = f.getWidth();
ew2 = f2.getWidth();
eh2 = f2.getHeight(false);
x1 = 2;
x2 = 2;
requiresleep1 = false;
requiresleep2 = false;
aftersleep = false;
autoscroll = false;
long start = System.nanoTime();
Termine result = Calculator.calcolarisultato("((5Ⓑ2+3√(100/0.1))*Ⓐ7+9/15*2√(26/2))/21");
long end = System.nanoTime();
long timeElapsed = end-start;
System.out.println("RESULT: " + result);
System.out.println("DECIMAl RESULT: " + result.getTerm().toBigDecimal());
System.out.println("Time elapsed: " + (double) timeElapsed / 1000000 + " milliseconds\n");
start = System.nanoTime();
RisultatoEquazione eresult = Calculator.calcolaequazione("((5Ⓑ2+3√(100/0.1))*Ⓐ7+9/15*2√(26/2))/21=(175*(2√7)+3*(2√13))/105");
end = System.nanoTime();
timeElapsed = end-start;
System.out.println("Is an equation: " + eresult.isAnEquation);
System.out.println("L-R: " + eresult.LR);
System.out.println("Time elapsed: " + (double) timeElapsed / 1000000 + " milliseconds\n");
} catch (Errore e) {
d.setBackground(0.99609375f,102f/256f,34f/256f);
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
d.errorStackTrace = sw.toString().toUpperCase().replace("\t", " ").replace("\r", "").split("\n");
d.error = e.id.toString();
System.err.println(e.id);
}
}
public void calcola(String eqn) {
equazione = eqn.replace("sqrt", "").replace("^", "");
try {
f = new Parentesi(equazione);
} catch (Errore e) {
e.printStackTrace();
}
try {
f2 = f.calcolaSistema();
} catch (Errore e) {
e.printStackTrace();
}
ew1 = f.getWidth();
ew2 = f2.getWidth();
eh2 = f2.getHeight(false);
x1 = 2;
x2 = 2;
requiresleep1 = false;
requiresleep2 = false;
aftersleep = false;
autoscroll = false;
}
@Override
public void beforeRender(float dt) {
endLoading += dt;
if (endLoading >= 2.5) {
d.loading = false;
}
}
@Override
public void render() {
d.setBackground(0.796875f, 0.90234375f, 0.828125f);
try {
// long delta = System.currentTimeMillis();
//
// if (equazione == "") {
// throw new Errore(Errori.SYNTAX_ERROR);
// } else {
// if (ew1 + x1 + 5 > screenSize[0] && !requiresleep1 && autoscroll) {
// x1-=1;
// } else if(autoscroll) {
// requiresleep1 = true;
// }
//
// if (ew2 + x2 + 5 > screenSize[0] && !requiresleep2 && autoscroll) {
// x2-=1;
// } else if(autoscroll) {
// requiresleep2 = true;
// }
//
// if (requiresleep1 && requiresleep2 && autoscroll) {
// requiresleep1 = false;
// requiresleep2 = false;
// try {
// Thread.sleep(500);
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// x1 = 2;
// x2 = 2;
// aftersleep = true;
// }
//
// f.draw(x1,2,d, false);
// f2.draw(x2,screenSize[1]-2-eh2,d, false);
// }
//
// if (aftersleep && autoscroll) {
// aftersleep = false;
// try {
// Thread.sleep(500);
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// }
//
// try {
// delta = System.currentTimeMillis() - delta;
// if (50-delta > 0 && autoscroll) {
// Thread.sleep(50-delta);
// }
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
if (false) {
throw new Errore(Errori.SYNTAX_ERROR);
}
} catch (Errore e) {
d.setBackground(0.99609375f,102f/256f,34f/256f);
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
d.errorStackTrace = sw.toString().toUpperCase().replace("\t", " ").replace("\r", "").split("\n");
d.error = e.id.toString();
System.err.println(e.id);
}
}
}