JSCL imported to C++

This commit is contained in:
serso 2016-01-24 21:03:04 +01:00
parent 1120864668
commit e751d2cbd4
299 changed files with 29254 additions and 5 deletions

View File

@ -74,7 +74,7 @@ dependencies {
compile 'org.solovyev.android:android-common-views:1.1.18@aar' compile 'org.solovyev.android:android-common-views:1.1.18@aar'
compile 'org.solovyev.android:android-common-menus:1.1.18@aar' compile 'org.solovyev.android:android-common-menus:1.1.18@aar'
compile 'org.solovyev.android:android-common-preferences:1.1.18@aar' compile 'org.solovyev.android:android-common-preferences:1.1.18@aar'
compile('org.solovyev:jscl:1.0.12') { compile(project(':jscl')) {
exclude(module: 'xercesImpl') exclude(module: 'xercesImpl')
} }
compile 'org.solovyev.android:checkout:0.7.2@aar' compile 'org.solovyev.android:checkout:0.7.2@aar'
@ -92,9 +92,6 @@ dependencies {
compile('com.google.guava:guava:11.0.2') { compile('com.google.guava:guava:11.0.2') {
exclude(module: 'jsr305') exclude(module: 'jsr305')
} }
compile('org.solovyev:jscl:1.0.11') {
exclude(module: 'xercesImpl')
}
compile('org.simpleframework:simple-xml:2.6.1') { compile('org.simpleframework:simple-xml:2.6.1') {
exclude(module: 'stax-api') exclude(module: 'stax-api')
exclude(module: 'xpp3') exclude(module: 'xpp3')

37
jscl/build.gradle Normal file
View File

@ -0,0 +1,37 @@
/*
* Copyright 2016 serso aka se.solovyev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
apply plugin: 'java'
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'org.solovyev:common-core:1.0.7'
compile 'org.solovyev:common-msg:1.0.7'
compile 'com.google.code.findbugs:annotations:2.0.1'
compile 'xerces:xercesImpl:2.8.0'
testCompile 'junit:junit:4.12'
testCompile 'net.sf.opencsv:opencsv:2.0'
}
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7

View File

@ -0,0 +1,67 @@
package jscl;
import jscl.text.msg.JsclMessage;
import org.solovyev.common.msg.Message;
import org.solovyev.common.msg.MessageLevel;
import org.solovyev.common.msg.MessageType;
import javax.annotation.Nonnull;
import java.util.List;
import java.util.Locale;
public abstract class AbstractJsclArithmeticException extends ArithmeticException implements Message {
@Nonnull
private final Message message;
public AbstractJsclArithmeticException(@Nonnull String messageCode, Object... parameters) {
this.message = new JsclMessage(messageCode, MessageType.error, parameters);
}
public AbstractJsclArithmeticException(@Nonnull Message message) {
this.message = message;
}
@Nonnull
public String getMessageCode() {
return this.message.getMessageCode();
}
@Nonnull
public List<Object> getParameters() {
return this.message.getParameters();
}
@Nonnull
public MessageLevel getMessageLevel() {
return this.message.getMessageLevel();
}
@Nonnull
public String getLocalizedMessage(@Nonnull Locale locale) {
return this.message.getLocalizedMessage(locale);
}
@Nonnull
@Override
public String getLocalizedMessage() {
return this.getLocalizedMessage(Locale.getDefault());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AbstractJsclArithmeticException that = (AbstractJsclArithmeticException) o;
if (!message.equals(that.message)) return false;
return true;
}
@Override
public int hashCode() {
return message.hashCode();
}
}

View File

@ -0,0 +1,119 @@
package jscl;
import jscl.math.Generic;
import jscl.math.NumericWrapper;
import jscl.math.numeric.Numeric;
import jscl.math.numeric.Real;
import javax.annotation.Nonnull;
public enum AngleUnit {
deg {
@Override
protected double getCoefficientTo(@Nonnull AngleUnit to) {
switch (to) {
case deg:
return 1d;
case rad:
return FROM_DEG_TO_RAD;
case grad:
return FROM_DEG_TO_GRAD;
case turns:
return FROM_DEG_TO_TURNS;
default:
throw new UnsupportedOperationException("Conversion from " + this + " to " + to + " is not supported!");
}
}
},
rad {
@Override
protected double getCoefficientTo(@Nonnull AngleUnit to) {
switch (to) {
case deg:
return FROM_RAD_TO_DEG;
case rad:
return 1d;
case grad:
return FROM_RAD_TO_GRAD;
case turns:
return FROM_RAD_TO_TURNS;
default:
throw new UnsupportedOperationException("Conversion from " + this + " to " + to + " is not supported!");
}
}
},
grad {
@Override
protected double getCoefficientTo(@Nonnull AngleUnit to) {
switch (to) {
case deg:
return FROM_GRAD_TO_DEG;
case rad:
return FROM_GRAD_TO_RAD;
case grad:
return 1d;
case turns:
return FROM_GRAD_TO_TURNS;
default:
throw new UnsupportedOperationException("Conversion from " + this + " to " + to + " is not supported!");
}
}
},
turns {
@Override
protected double getCoefficientTo(@Nonnull AngleUnit to) {
switch (to) {
case deg:
return FROM_TURNS_TO_DEG;
case rad:
return FROM_TURNS_TO_RAD;
case grad:
return FROM_TURNS_TO_GRAD;
case turns:
return 1d;
default:
throw new UnsupportedOperationException("Conversion from " + this + " to " + to + " is not supported!");
}
}
};
private static final double FROM_RAD_TO_DEG = 180d / Math.PI;
private static final double FROM_RAD_TO_GRAD = 200d / Math.PI;
private static final double FROM_RAD_TO_TURNS = 0.5d / Math.PI;
private static final double FROM_DEG_TO_RAD = Math.PI / 180d;
private static final double FROM_DEG_TO_TURNS = 0.5d / 180d;
private static final double FROM_DEG_TO_GRAD = 10d / 9d;
private static final double FROM_GRAD_TO_RAD = Math.PI / 200d;
private static final double FROM_GRAD_TO_TURNS = 0.5d / 200d;
private static final double FROM_GRAD_TO_DEG = 9d / 10d;
private static final double FROM_TURNS_TO_GRAD = 200d / 0.5d;
private static final double FROM_TURNS_TO_RAD = Math.PI / 0.5d;
private static final double FROM_TURNS_TO_DEG = 180d / 0.5d;
public final double transform(@Nonnull AngleUnit to, double value) {
return value * getCoefficientTo(to);
}
protected abstract double getCoefficientTo(@Nonnull AngleUnit to);
public final Numeric transform(@Nonnull AngleUnit to, @Nonnull Numeric value) {
return value.multiply(getRealCoefficientTo(to));
}
private Real getRealCoefficientTo(@Nonnull AngleUnit to) {
return Real.valueOf(getCoefficientTo(to));
}
public final Generic transform(@Nonnull AngleUnit to, @Nonnull Generic value) {
return value.multiply(new NumericWrapper(getRealCoefficientTo(to)));
}
}

View File

@ -0,0 +1,14 @@
package jscl;
import jscl.math.function.CustomFunction;
import jscl.text.msg.Messages;
import org.solovyev.common.msg.Message;
import javax.annotation.Nonnull;
public class CustomFunctionCalculationException extends AbstractJsclArithmeticException {
public CustomFunctionCalculationException(@Nonnull CustomFunction function, @Nonnull Message message) {
super(Messages.msg_19, function.getName(), message);
}
}

View File

@ -0,0 +1,54 @@
package jscl;
import org.solovyev.common.msg.Message;
import org.solovyev.common.msg.MessageRegistry;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.NotThreadSafe;
import java.util.ArrayList;
import java.util.List;
@NotThreadSafe
public class FixedCapacityListMessageRegistry implements MessageRegistry {
@Nonnull
private final List<Message> messages;
private final int capacity;
private volatile int size;
public FixedCapacityListMessageRegistry(int capacity) {
this.size = 0;
this.capacity = capacity;
this.messages = new ArrayList<Message>(capacity);
}
@edu.umd.cs.findbugs.annotations.SuppressWarnings(value = {"VO_VOLATILE_INCREMENT"}, justification = "NotThreadSafe - outer synchronization")
public void addMessage(@Nonnull Message message) {
if (!this.messages.contains(message)) {
if (this.size <= this.capacity) {
this.messages.add(message);
this.size++;
} else {
this.messages.remove(0);
this.messages.add(message);
}
}
}
@edu.umd.cs.findbugs.annotations.SuppressWarnings(value = {"VO_VOLATILE_INCREMENT"}, justification = "NotThreadSafe - outer synchronization")
@Nonnull
public Message getMessage() {
if (hasMessage()) {
this.size--;
return messages.remove(0);
} else {
throw new IllegalStateException("No messages!");
}
}
public boolean hasMessage() {
return size > 0;
}
}

View File

@ -0,0 +1,345 @@
package jscl;
import jscl.math.Expression;
import jscl.math.Generic;
import jscl.math.NotIntegerException;
import jscl.math.function.*;
import jscl.math.operator.Operator;
import jscl.math.operator.Percent;
import jscl.math.operator.Rand;
import jscl.math.operator.matrix.OperatorsRegistry;
import jscl.text.ParseException;
import org.solovyev.common.JPredicate;
import org.solovyev.common.collections.Collections;
import org.solovyev.common.math.MathRegistry;
import org.solovyev.common.msg.MessageRegistry;
import org.solovyev.common.msg.Messages;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
public class JsclMathEngine implements MathEngine {
public static final AngleUnit DEFAULT_ANGLE_UNITS = AngleUnit.deg;
public static final NumeralBase DEFAULT_NUMERAL_BASE = NumeralBase.dec;
public static final String GROUPING_SEPARATOR_DEFAULT = " ";
public static final int MAX_FRACTION_DIGITS = 20;
@Nonnull
private static JsclMathEngine instance = new JsclMathEngine();
@Nonnull
private DecimalFormatSymbols decimalGroupSymbols = new DecimalFormatSymbols(Locale.getDefault());
private boolean roundResult = false;
private boolean scienceNotation = false;
private int precision = 5;
private boolean useGroupingSeparator = false;
@Nonnull
private AngleUnit angleUnits = DEFAULT_ANGLE_UNITS;
@Nonnull
private NumeralBase numeralBase = DEFAULT_NUMERAL_BASE;
@Nonnull
private ConstantsRegistry constantsRegistry;
@Nonnull
private MessageRegistry messageRegistry = Messages.synchronizedMessageRegistry(new FixedCapacityListMessageRegistry(10));
{
decimalGroupSymbols.setDecimalSeparator('.');
decimalGroupSymbols.setGroupingSeparator(GROUPING_SEPARATOR_DEFAULT.charAt(0));
}
private JsclMathEngine() {
this.constantsRegistry = new ConstantsRegistry();
}
@Nonnull
public static JsclMathEngine getInstance() {
return instance;
}
private static int integerValue(final double value) throws NotIntegerException {
if (Math.floor(value) == value) {
return (int) value;
} else {
throw new NotIntegerException();
}
}
@Nonnull
public String evaluate(@Nonnull String expression) throws ParseException {
return evaluateGeneric(expression).toString();
}
@Nonnull
public String simplify(@Nonnull String expression) throws ParseException {
return simplifyGeneric(expression).toString();
}
@Nonnull
public String elementary(@Nonnull String expression) throws ParseException {
return elementaryGeneric(expression).toString();
}
@Nonnull
public Generic evaluateGeneric(@Nonnull String expression) throws ParseException {
if (expression.contains(Percent.NAME) || expression.contains(Rand.NAME)) {
return Expression.valueOf(expression).numeric();
} else {
return Expression.valueOf(expression).expand().numeric();
}
}
@Nonnull
public Generic simplifyGeneric(@Nonnull String expression) throws ParseException {
if (expression.contains(Percent.NAME) || expression.contains(Rand.NAME)) {
return Expression.valueOf(expression);
} else {
return Expression.valueOf(expression).expand().simplify();
}
}
@Nonnull
public Generic elementaryGeneric(@Nonnull String expression) throws ParseException {
return Expression.valueOf(expression).elementary();
}
@Nonnull
public MathRegistry<Function> getFunctionsRegistry() {
return FunctionsRegistry.getInstance();
}
@Nonnull
public MathRegistry<Operator> getOperatorsRegistry() {
return OperatorsRegistry.getInstance();
}
@Nonnull
public MathRegistry<Operator> getPostfixFunctionsRegistry() {
return PostfixFunctionsRegistry.getInstance();
}
@Nonnull
public AngleUnit getAngleUnits() {
return angleUnits;
}
public void setAngleUnits(@Nonnull AngleUnit angleUnits) {
this.angleUnits = angleUnits;
}
@Nonnull
public NumeralBase getNumeralBase() {
return numeralBase;
}
public void setNumeralBase(@Nonnull NumeralBase numeralBase) {
this.numeralBase = numeralBase;
}
@Nonnull
public MathRegistry<IConstant> getConstantsRegistry() {
return constantsRegistry;
}
@Nonnull
public String format(@Nonnull Double value) throws NumeralBaseException {
return format(value, numeralBase);
}
@Nonnull
public String format(@Nonnull Double value, @Nonnull NumeralBase nb) throws NumeralBaseException {
if (value.isInfinite()) {
// return predefined constant for infinity
if (value >= 0) {
return Constants.INF.getName();
} else {
return Constants.INF.expressionValue().negate().toString();
}
} else {
if (value.isNaN()) {
// return "NaN"
return String.valueOf(value);
} else {
if (nb == NumeralBase.dec) {
// decimal numeral base => do specific formatting
// detect if current number is precisely equals to constant in constants' registry (NOTE: ONLY FOR SYSTEM CONSTANTS)
final Double localValue = value;
IConstant constant = Collections.find(this.getConstantsRegistry().getSystemEntities(), new JPredicate<IConstant>() {
public boolean apply(@Nullable IConstant constant) {
if (constant != null) {
if (localValue.equals(constant.getDoubleValue())) {
if (!constant.getName().equals(Constants.PI_INV.getName())) {
if (!constant.getName().equals(Constants.PI.getName()) || JsclMathEngine.getInstance().getAngleUnits() == AngleUnit.rad) {
return true;
}
}
}
}
return false;
}
});
if (constant == null) {
final IConstant piInv = this.getConstantsRegistry().get(Constants.PI_INV.getName());
if (piInv != null && value.equals(piInv.getDoubleValue())) {
constant = piInv;
}
}
if (constant == null) {
// prepare decimal format
final DecimalFormat df;
if (roundResult) {
value = new BigDecimal(value).setScale(precision, BigDecimal.ROUND_HALF_UP).doubleValue();
}
if (value != 0d && value != -0d) {
if (Math.abs(value) < Math.pow(10, -5) || scienceNotation) {
df = new DecimalFormat("##0.#####E0");
} else {
df = new DecimalFormat();
}
} else {
df = new DecimalFormat();
}
df.setDecimalFormatSymbols(decimalGroupSymbols);
df.setGroupingUsed(useGroupingSeparator);
df.setGroupingSize(nb.getGroupingSize());
if (!scienceNotation) {
// using default round logic => try roundResult variable
if (!roundResult) {
// set maximum fraction digits high enough to show all fraction digits in case of no rounding
df.setMaximumFractionDigits(MAX_FRACTION_DIGITS);
} else {
df.setMaximumFractionDigits(precision);
}
}
return df.format(value);
} else {
return constant.getName();
}
} else {
return convert(value, nb);
}
}
}
}
@Nonnull
public String convert(@Nonnull Double value, @Nonnull NumeralBase to) {
String ungroupedValue;
try {
// check if double can be converted to integer
integerValue(value);
ungroupedValue = to.toString(new BigDecimal(value).toBigInteger());
} catch (NotIntegerException e) {
ungroupedValue = to.toString(value, roundResult ? precision : MAX_FRACTION_DIGITS);
}
return addGroupingSeparators(to, ungroupedValue);
}
@Nonnull
public MessageRegistry getMessageRegistry() {
return messageRegistry;
}
public void setMessageRegistry(@Nonnull MessageRegistry messageRegistry) {
this.messageRegistry = messageRegistry;
}
@Nonnull
public String addGroupingSeparators(@Nonnull NumeralBase nb, @Nonnull String ungroupedDoubleValue) {
if (useGroupingSeparator) {
String groupingSeparator = nb == NumeralBase.dec ? String.valueOf(decimalGroupSymbols.getGroupingSeparator()) : " ";
final int dotIndex = ungroupedDoubleValue.indexOf(".");
String ungroupedValue;
if (dotIndex >= 0) {
ungroupedValue = ungroupedDoubleValue.substring(0, dotIndex);
} else {
ungroupedValue = ungroupedDoubleValue;
}
// inject group separator in the resulted string
// NOTE: space symbol is always used!!!
StringBuilder result = insertSeparators(nb, groupingSeparator, ungroupedValue, true);
result = result.reverse();
if (dotIndex >= 0) {
result.append(insertSeparators(nb, groupingSeparator, ungroupedDoubleValue.substring(dotIndex), false));
}
return result.toString();
} else {
return ungroupedDoubleValue;
}
}
@Nonnull
private StringBuilder insertSeparators(@Nonnull NumeralBase nb,
@Nonnull String groupingSeparator,
@Nonnull String value,
boolean reversed) {
final StringBuilder result = new StringBuilder(value.length() + nb.getGroupingSize() * groupingSeparator.length());
if (reversed) {
for (int i = value.length() - 1; i >= 0; i--) {
result.append(value.charAt(i));
if (i != 0 && (value.length() - i) % nb.getGroupingSize() == 0) {
result.append(groupingSeparator);
}
}
} else {
for (int i = 0; i < value.length(); i++) {
result.append(value.charAt(i));
if (i != 0 && i != value.length() - 1 && i % nb.getGroupingSize() == 0) {
result.append(groupingSeparator);
}
}
}
return result;
}
public void setDecimalGroupSymbols(@Nonnull DecimalFormatSymbols decimalGroupSymbols) {
this.decimalGroupSymbols = decimalGroupSymbols;
}
public void setRoundResult(boolean roundResult) {
this.roundResult = roundResult;
}
public void setPrecision(int precision) {
this.precision = precision;
}
public void setUseGroupingSeparator(boolean useGroupingSeparator) {
this.useGroupingSeparator = useGroupingSeparator;
}
public void setScienceNotation(boolean scienceNotation) {
this.scienceNotation = scienceNotation;
}
public char getGroupingSeparator() {
return this.decimalGroupSymbols.getGroupingSeparator();
}
public void setGroupingSeparator(char groupingSeparator) {
this.decimalGroupSymbols.setGroupingSeparator(groupingSeparator);
}
}

View File

@ -0,0 +1,59 @@
package jscl;
import jscl.math.function.Function;
import jscl.math.function.IConstant;
import jscl.math.operator.Operator;
import org.solovyev.common.math.MathRegistry;
import javax.annotation.Nonnull;
import java.text.DecimalFormatSymbols;
public interface MathContext {
@Nonnull
MathRegistry<Function> getFunctionsRegistry();
@Nonnull
MathRegistry<Operator> getOperatorsRegistry();
@Nonnull
MathRegistry<IConstant> getConstantsRegistry();
@Nonnull
MathRegistry<Operator> getPostfixFunctionsRegistry();
@Nonnull
AngleUnit getAngleUnits();
void setAngleUnits(@Nonnull AngleUnit defaultAngleUnits);
@Nonnull
NumeralBase getNumeralBase();
// OUTPUT NUMBER FORMATTING
// todo serso: maybe gather all formatting data in one object?
void setNumeralBase(@Nonnull NumeralBase numeralBase);
void setDecimalGroupSymbols(@Nonnull DecimalFormatSymbols decimalGroupSymbols);
void setRoundResult(boolean roundResult);
void setPrecision(int precision);
void setUseGroupingSeparator(boolean useGroupingSeparator);
void setGroupingSeparator(char groupingSeparator);
@Nonnull
String format(@Nonnull Double value) throws NumeralBaseException;
@Nonnull
String format(@Nonnull Double value, @Nonnull NumeralBase nb) throws NumeralBaseException;
@Nonnull
String addGroupingSeparators(@Nonnull NumeralBase nb, @Nonnull String ungroupedIntValue);
void setScienceNotation(boolean scienceNotation);
}

View File

@ -0,0 +1,36 @@
package jscl;
import jscl.math.Generic;
import jscl.text.ParseException;
import org.solovyev.common.msg.MessageRegistry;
import javax.annotation.Nonnull;
public interface MathEngine extends MathContext {
@Nonnull
String evaluate(@Nonnull String expression) throws ParseException;
@Nonnull
String simplify(@Nonnull String expression) throws ParseException;
@Nonnull
String elementary(@Nonnull String expression) throws ParseException;
@Nonnull
Generic evaluateGeneric(@Nonnull String expression) throws ParseException;
@Nonnull
Generic simplifyGeneric(@Nonnull String expression) throws ParseException;
@Nonnull
Generic elementaryGeneric(@Nonnull String expression) throws ParseException;
@Nonnull
String convert(@Nonnull Double value, @Nonnull NumeralBase to);
@Nonnull
MessageRegistry getMessageRegistry();
void setMessageRegistry(@Nonnull MessageRegistry messageRegistry);
}

View File

@ -0,0 +1,10 @@
package jscl;
import javax.annotation.Nonnull;
public class NotSupportedException extends AbstractJsclArithmeticException {
public NotSupportedException(@Nonnull String messageCode, Object... parameters) {
super(messageCode, parameters);
}
}

View File

@ -0,0 +1,170 @@
package jscl;
import jscl.math.JsclInteger;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
public enum NumeralBase {
dec(10, 3) {
private final List<Character> characters = Arrays.asList('0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
@Nonnull
@Override
public Double toDouble(@Nonnull String doubleString) {
return Double.valueOf(doubleString);
}
@Nonnull
public String toString(@Nonnull Double value) {
return value.toString();
}
@Nonnull
@Override
public String getJsclPrefix() {
return "0d:";
}
@Nonnull
@Override
public List<Character> getAcceptableCharacters() {
return characters;
}
},
hex(16, 2) {
private final List<Character> characters = Arrays.asList('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
@Nonnull
@Override
public String getJsclPrefix() {
return "0x:";
}
@Nonnull
@Override
public List<Character> getAcceptableCharacters() {
return characters;
}
},
oct(8, 4) {
private final List<Character> characters = Arrays.asList('0', '1', '2', '3', '4', '5', '6', '7');
@Nonnull
@Override
public String getJsclPrefix() {
return "0o:";
}
@Nonnull
@Override
public List<Character> getAcceptableCharacters() {
return characters;
}
},
bin(2, 4) {
private final List<Character> characters = Arrays.asList('0', '1');
@Nonnull
@Override
public String getJsclPrefix() {
return "0b:";
}
@Nonnull
@Override
public List<Character> getAcceptableCharacters() {
return characters;
}
};
protected final int radix;
protected final int groupingSize;
NumeralBase(int radix, int groupingSize) {
this.radix = radix;
this.groupingSize = groupingSize;
}
@Nullable
public static NumeralBase getByPrefix(@Nonnull String prefix) {
for (NumeralBase nb : NumeralBase.values()) {
if (prefix.equals(nb.getJsclPrefix())) {
return nb;
}
}
return null;
}
@Nonnull
protected static String toString(@Nonnull Double value, int radix, int fractionDigits) {
final BigDecimal mult = BigDecimal.valueOf(radix).pow(fractionDigits);
final BigDecimal bd = BigDecimal.valueOf(value).multiply(mult);
final BigInteger bi = bd.toBigInteger();
final StringBuilder result = new StringBuilder(bi.toString(radix));
while (result.length() < fractionDigits + 1) { // +1 for leading zero
result.insert(0, "0");
}
result.insert(result.length() - fractionDigits, ".");
return result.toString().toUpperCase();
}
@Nonnull
public Double toDouble(@Nonnull String doubleString) throws NumberFormatException {
return Double.longBitsToDouble(Long.valueOf(doubleString, radix));
}
@Nonnull
public Integer toInteger(@Nonnull String integerString) throws NumberFormatException {
return Integer.valueOf(integerString, radix);
}
@Nonnull
public JsclInteger toJsclInteger(@Nonnull String integerString) throws NumberFormatException {
return new JsclInteger(toBigInteger(integerString));
}
@Nonnull
public BigInteger toBigInteger(@Nonnull String value) throws NumberFormatException {
return new BigInteger(value, radix);
}
public String toString(@Nonnull BigInteger value) {
return value.toString(radix).toUpperCase();
}
public String toString(@Nonnull Integer value) {
return Integer.toString(value, radix).toUpperCase();
}
@Nonnull
public abstract String getJsclPrefix();
@Nonnull
public abstract List<Character> getAcceptableCharacters();
public int getGroupingSize() {
return groupingSize;
}
@Nonnull
public String toString(@Nonnull Double value, int fractionDigits) {
return toString(value, radix, fractionDigits);
}
}

View File

@ -0,0 +1,12 @@
package jscl;
import jscl.text.msg.Messages;
import javax.annotation.Nonnull;
public class NumeralBaseException extends AbstractJsclArithmeticException {
public NumeralBaseException(@Nonnull Double value) {
super(Messages.msg_17, value);
}
}

View File

@ -0,0 +1,232 @@
package jscl.math;
import jscl.math.function.*;
import jscl.math.polynomial.Monomial;
import jscl.math.polynomial.Polynomial;
import jscl.math.polynomial.UnivariatePolynomial;
import javax.annotation.Nonnull;
public class AntiDerivative {
UnivariatePolynomial factory;
PolynomialWithSyzygy syzygy;
Generic result;
AntiDerivative(Variable variable) {
factory = (UnivariatePolynomial) Polynomial.factory(variable);
syzygy = (PolynomialWithSyzygy) PolynomialWithSyzygy.factory(variable);
}
public static Generic compute(Fraction fraction, Variable variable) {
AntiDerivative s = new AntiDerivative(variable);
s.compute(fraction);
return s.getValue();
}
public static Generic compute(Root root, Variable variable) throws NotIntegrableException {
int d = root.degree();
Generic a[] = root.getParameters();
boolean b = d > 0;
b = b && a[0].negate().isIdentity(variable);
for (int i = 1; i < d; i++) b = b && a[i].signum() == 0;
b = b && a[d].compareTo(JsclInteger.valueOf(1)) == 0;
if (b) {
return new Pow(
a[0].negate(),
new Inverse(JsclInteger.valueOf(d)).selfExpand()
).antiDerivative(0);
} else {
throw new NotIntegrableException();
}
}
void compute(Fraction fraction) {
Debug.println("antiDerivative");
Debug.increment();
Generic g[] = fraction.getParameters();
Generic r[] = reduce(g[0], g[1]);
r = divideAndRemainder(r[0], r[1]);
Generic s = new Inverse(r[2]).selfExpand();
Generic p = r[0].multiply(s);
Generic a = r[1].multiply(s);
result = p.antiDerivative(factory.variable()).add(hermite(a, g[1]));
Debug.decrement();
}
Generic[] reduce(Generic n, Generic d) {
Debug.println("reduce(" + n + ", " + d + ")");
Polynomial pn = factory.valueOf(n);
Polynomial pd = factory.valueOf(d);
Polynomial gcd = pn.gcd(pd);
return new Generic[]{
pn.divide(gcd).genericValue(),
pd.divide(gcd).genericValue()
};
}
Generic[] divideAndRemainder(Generic n, Generic d) {
Debug.println("divideAndRemainder(" + n + ", " + d + ")");
Polynomial pn = syzygy.valueof(n, 0);
Polynomial pd = syzygy.valueof(d, 1);
PolynomialWithSyzygy pr = (PolynomialWithSyzygy) pn.remainderUpToCoefficient(pd);
return new Generic[]{
pr.syzygy[1].genericValue().negate(),
pr.genericValue(),
pr.syzygy[0].genericValue()
};
}
Generic[] bezout(Generic a, Generic b) {
Debug.println("bezout(" + a + ", " + b + ")");
Polynomial pa = syzygy.valueof(a, 0);
Polynomial pb = syzygy.valueof(b, 1);
PolynomialWithSyzygy gcd = (PolynomialWithSyzygy) pa.gcd(pb);
return new Generic[]{
gcd.syzygy[0].genericValue(),
gcd.syzygy[1].genericValue(),
gcd.genericValue()
};
}
Generic hermite(Generic a, Generic d) {
Debug.println("hermite(" + a + ", " + d + ")");
UnivariatePolynomial sd[] = ((UnivariatePolynomial) factory.valueOf(d)).squarefreeDecomposition();
int m = sd.length - 1;
if (m < 2) return trager(a, d);
else {
Generic u = sd[0].genericValue();
for (int i = 1; i < m; i++) {
u = u.multiply(sd[i].genericValue().pow(i));
}
Generic v = sd[m].genericValue();
Generic vprime = sd[m].derivative().genericValue();
Generic uvprime = u.multiply(vprime);
Generic r[] = bezout(uvprime, v);
Generic b = r[0].multiply(a);
Generic c = r[1].multiply(a);
Generic s = r[2];
r = divideAndRemainder(b, v);
b = r[1];
c = c.multiply(r[2]).add(r[0].multiply(uvprime));
s = new Inverse(s.multiply(r[2]).multiply(JsclInteger.valueOf(1 - m))).selfExpand();
b = b.multiply(s);
c = c.multiply(s);
Generic bprime = ((UnivariatePolynomial) factory.valueOf(b)).derivative().genericValue();
return new Fraction(b, v.pow(m - 1)).selfExpand().add(hermite(JsclInteger.valueOf(1 - m).multiply(c).subtract(u.multiply(bprime)), u.multiply(v.pow(m - 1))));
}
}
Generic trager(Generic a, Generic d) {
Debug.println("trager(" + a + ", " + d + ")");
Variable t = new TechnicalVariable("t");
UnivariatePolynomial pd = (UnivariatePolynomial) factory.valueOf(d);
UnivariatePolynomial pa = (UnivariatePolynomial) factory.valueOf(a).subtract(pd.derivative().multiply(t.expressionValue()));
UnivariatePolynomial rs[] = pd.remainderSequence(pa);
Polynomial fact = UnivariatePolynomial.factory(t);
for (int i = 0; i < rs.length; i++)
if (rs[i] != null)
rs[i] = (UnivariatePolynomial) fact.valueOf((i > 0 ? rs[i].normalize() : rs[i]).genericValue());
UnivariatePolynomial q[] = rs[0].squarefreeDecomposition();
int m = q.length - 1;
Generic s = JsclInteger.valueOf(0);
for (int i = 1; i <= m; i++) {
for (int j = 0; j < q[i].degree(); j++) {
Generic a2 = new Root(q[i], j).selfExpand();
s = s.add(a2.multiply(new Ln(i == pd.degree() ? d : rs[i].substitute(a2)).selfExpand()));
}
}
return s;
}
Generic getValue() {
return result;
}
}
class PolynomialWithSyzygy extends UnivariatePolynomial {
Polynomial syzygy[] = new Polynomial[2];
PolynomialWithSyzygy(Variable variable) {
super(variable);
}
public static Polynomial factory(Variable variable) {
return new PolynomialWithSyzygy(variable);
}
@Nonnull
public Polynomial subtract(@Nonnull Polynomial that) {
PolynomialWithSyzygy p2 = (PolynomialWithSyzygy) that;
PolynomialWithSyzygy p = (PolynomialWithSyzygy) super.subtract(p2);
for (int i = 0; i < syzygy.length; i++) p.syzygy[i] = syzygy[i].subtract(p2.syzygy[i]);
return p;
}
public Polynomial multiply(Generic generic) {
PolynomialWithSyzygy p = (PolynomialWithSyzygy) super.multiply(generic);
for (int i = 0; i < syzygy.length; i++) p.syzygy[i] = syzygy[i].multiply(generic);
return p;
}
public Polynomial multiply(Monomial monomial, Generic generic) {
PolynomialWithSyzygy p = (PolynomialWithSyzygy) super.multiply(monomial, generic);
for (int i = 0; i < syzygy.length; i++) p.syzygy[i] = syzygy[i].multiply(monomial).multiply(generic);
return p;
}
public Polynomial divide(Generic generic) throws ArithmeticException {
PolynomialWithSyzygy p = (PolynomialWithSyzygy) super.divide(generic);
for (int i = 0; i < syzygy.length; i++) p.syzygy[i] = syzygy[i].divide(generic);
return p;
}
public Polynomial remainderUpToCoefficient(Polynomial polynomial) throws ArithmeticException {
PolynomialWithSyzygy p = this;
PolynomialWithSyzygy q = (PolynomialWithSyzygy) polynomial;
if (p.signum() == 0) return p;
int d = p.degree();
int d2 = q.degree();
for (int i = d - d2; i >= 0; i--) {
Generic c1 = p.get(i + d2);
Generic c2 = q.get(d2);
Generic c = c1.gcd(c2);
c1 = c1.divide(c);
c2 = c2.divide(c);
p = (PolynomialWithSyzygy) p.multiply(c2).subtract(q.multiply(monomial(Literal.valueOf(variable, i)), c1)).normalize();
}
return p;
}
public Polynomial gcd(Polynomial polynomial) {
Polynomial p = this;
Polynomial q = polynomial;
while (q.signum() != 0) {
Polynomial r = p.remainderUpToCoefficient(q);
p = q;
q = r;
}
return p;
}
public Generic gcd() {
Generic a = super.gcd();
for (int i = 0; i < syzygy.length; i++) a = a.gcd(syzygy[i].gcd());
return a.signum() == signum() ? a : a.negate();
}
public PolynomialWithSyzygy valueof(Generic generic, int n) {
PolynomialWithSyzygy p = (PolynomialWithSyzygy) newinstance();
p.init(generic, n);
return p;
}
void init(Generic generic, int n) {
init(generic);
for (int i = 0; i < syzygy.length; i++)
syzygy[i] = Polynomial.factory(variable).valueOf(JsclInteger.valueOf(i == n ? 1 : 0));
}
protected UnivariatePolynomial newinstance() {
return new PolynomialWithSyzygy(variable);
}
}

View File

@ -0,0 +1,19 @@
package jscl.math;
import javax.annotation.Nonnull;
public interface Arithmetic<T extends Arithmetic<T>> {
@Nonnull
T add(@Nonnull T that);
@Nonnull
T subtract(@Nonnull T that);
@Nonnull
T multiply(@Nonnull T that);
@Nonnull
T divide(@Nonnull T that) throws NotDivisibleException;
}

View File

@ -0,0 +1,110 @@
package jscl.math;
/**
* User: serso
* Date: 12/26/11
* Time: 9:45 AM
*/
class Clifford {
int p, n;
int operator[][];
Clifford(int algebra[]) {
this(algebra[0], algebra[1]);
}
Clifford(int p, int q) {
this.p = p;
n = p + q;
int m = 1 << n;
operator = new int[m][m];
for (int i = 0; i < m; i++) {
for (int j = 0; j < m; j++) {
int a = combination(i, n);
int b = combination(j, n);
int c = a ^ b;
int l = location(c, n);
boolean s = sign(a, b);
int k = l + 1;
operator[i][j] = s ? -k : k;
}
}
}
static int combination(int l, int n) {
if (n <= 2) return l;
int b[] = new int[1];
int l1 = decimation(l, n, b);
int c = combination(l1, n - 1);
return (c << 1) + b[0];
}
static int location(int c, int n) {
if (n <= 2) return c;
int c1 = c >> 1;
int b = c & 1;
int l1 = location(c1, n - 1);
return dilatation(l1, n, new int[]{b});
}
static int decimation(int l, int n, int b[]) {
int p = grade(l, n - 1, 1);
int p1 = (p + 1) >> 1;
b[0] = p & 1;
return l - sum(p1, n - 1);
}
static int dilatation(int l, int n, int b[]) {
int p1 = grade(l, n - 1);
return l + sum(p1 + b[0], n - 1);
}
static int grade(int l, int n) {
return grade(l, n, 0);
}
static int grade(int l, int n, int d) {
int s = 0, p = 0;
while (true) {
s += binomial(n, p >> d);
if (s <= l) p++;
else break;
}
return p;
}
static int sum(int p, int n) {
int q = 0, s = 0;
while (q < p) s += binomial(n, q++);
return s;
}
static int binomial(int n, int p) {
int a = 1, b = 1;
for (int i = n - p + 1; i <= n; i++) a *= i;
for (int i = 2; i <= p; i++) b *= i;
return a / b;
}
static int log2e(int n) {
int i;
for (i = 0; n > 1; n >>= 1) i++;
return i;
}
boolean sign(int a, int b) {
boolean s = false;
for (int i = 0; i < n; i++) {
if ((b & (1 << i)) > 0) {
for (int j = i; j < n; j++) {
if ((a & (1 << j)) > 0 && (j > i || i >= p)) s = !s;
}
}
}
return s;
}
int[][] operator() {
return operator;
}
}

View File

@ -0,0 +1,41 @@
package jscl.math;
import java.io.PrintStream;
public class Debug {
private static PrintStream out;
private static int indentation;
private Debug() {
}
public static void println(Object x) {
if (out != null) {
for (int i = 0; i < indentation; i++) {
out.print(" ");
}
out.println(x);
}
}
public static PrintStream getOutputStream() {
return out;
}
public static void setOutputStream(PrintStream out) {
Debug.out = out;
}
public static void increment() {
indentation++;
}
public static void decrement() {
indentation--;
}
public static void reset() {
indentation = 0;
}
}

View File

@ -0,0 +1,49 @@
package jscl.math;
import javax.annotation.Nonnull;
public class DoubleVariable extends GenericVariable {
public DoubleVariable(Generic generic) {
super(generic);
}
public JsclInteger symbolic() {
return content.integerValue();
}
public Generic antiDerivative(Variable variable) throws NotIntegrableException {
return expressionValue().multiply(variable.expressionValue());
}
@Nonnull
public Generic derivative(Variable variable) {
return JsclInteger.valueOf(0);
}
public Generic substitute(Variable variable, Generic generic) {
if (isIdentity(variable)) return generic;
else return expressionValue();
}
public Generic expand() {
return expressionValue();
}
public Generic factorize() {
return expressionValue();
}
public Generic elementary() {
return expressionValue();
}
public Generic simplify() {
return expressionValue();
}
@Nonnull
public Variable newInstance() {
return new DoubleVariable(null);
}
}

View File

@ -0,0 +1,887 @@
package jscl.math;
import jscl.JsclMathEngine;
import jscl.math.function.Constant;
import jscl.math.function.Fraction;
import jscl.math.function.Inverse;
import jscl.math.numeric.Real;
import jscl.math.polynomial.Polynomial;
import jscl.math.polynomial.UnivariatePolynomial;
import jscl.mathml.MathML;
import jscl.text.*;
import jscl.text.msg.Messages;
import jscl.util.ArrayUtils;
import org.solovyev.common.Converter;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
public class Expression extends Generic {
protected static final Converter<Variable, Generic> FACTORIZE_CONVERTER = new Converter<Variable, Generic>() {
@Nonnull
public Generic convert(@Nonnull Variable variable) {
return variable.factorize();
}
};
protected static final Converter<Variable, Generic> ELEMENTARY_CONVERTER = new Converter<Variable, Generic>() {
@Nonnull
public Generic convert(@Nonnull Variable variable) {
return variable.elementary();
}
};
protected static final Converter<Variable, Generic> EXPAND_CONVERTER = new Converter<Variable, Generic>() {
@Nonnull
public Generic convert(@Nonnull Variable variable) {
return variable.expand();
}
};
protected static final Converter<Variable, Generic> NUMERIC_CONVERTER = new Converter<Variable, Generic>() {
@Nonnull
public Generic convert(@Nonnull Variable variable) {
return variable.numeric();
}
};
int size;
private Literal literals[];
private JsclInteger coefficients[];
Expression() {
}
Expression(int size) {
init(size);
}
public static Variable[] variables(Generic elements[]) {
final List<Variable> result = new ArrayList<Variable>();
for (Generic element : elements) {
for (Variable variable : element.variables()) {
if (!result.contains(variable)) {
result.add(variable);
}
}
}
return ArrayUtils.toArray(result, new Variable[result.size()]);
}
@Nonnull
public static Expression valueOf(@Nonnull Variable variable) {
return valueOf(Literal.valueOf(variable));
}
@Nonnull
public static Expression valueOf(@Nonnull Literal literal) {
return valueOf(literal, JsclInteger.valueOf(1));
}
@Nonnull
public static Expression valueOf(@Nonnull JsclInteger integer) {
return valueOf(Literal.newInstance(), integer);
}
@Nonnull
public static Expression valueOf(@Nonnull Literal literal, @Nonnull JsclInteger integer) {
final Expression result = new Expression();
result.init(literal, integer);
return result;
}
public static Expression valueOf(Rational rational) {
Expression ex = new Expression();
ex.init(rational);
return ex;
}
public static Expression valueOf(@Nonnull Constant constant) {
final Expression expression = new Expression(1);
Literal literal = new Literal();
literal.init(constant, 1);
expression.init(literal, JsclInteger.ONE);
return expression;
}
public static Expression valueOf(@Nonnull Double value) {
final Expression expression = new Expression(1);
Literal literal = new Literal();
literal.init(new DoubleVariable(new NumericWrapper(Real.valueOf(value))), 1);
expression.init(literal, JsclInteger.ONE);
return expression;
}
public static Expression valueOf(@Nonnull String expression) throws ParseException {
final MutableInt position = new MutableInt(0);
final Parser.Parameters p = Parser.Parameters.newInstance(expression, position, JsclMathEngine.getInstance());
final Generic generic = ExpressionParser.parser.parse(p, null);
ParserUtils.skipWhitespaces(p);
int index = position.intValue();
if (index < expression.length()) {
throw new ParseException(Messages.msg_1, index, expression, index + 1);
}
return new Expression().init(generic);
}
public static Expression init(@Nonnull NumericWrapper numericWrapper) {
final Expression expression = new Expression(1);
Literal literal = new Literal();
literal.init(new ExpressionVariable(numericWrapper), 1);
expression.init(literal, JsclInteger.ONE);
return expression;
}
public static void separateSign(MathML element, Generic generic) {
if (generic.signum() < 0) {
MathML e1 = element.element("mo");
e1.appendChild(element.text("-"));
element.appendChild(e1);
generic.negate().toMathML(element, null);
} else {
generic.toMathML(element, null);
}
}
public int size() {
return size;
}
public Literal literal(int n) {
return literals[n];
}
public JsclInteger coef(int n) {
return coefficients[n];
}
void init(int size) {
literals = new Literal[size];
coefficients = new JsclInteger[size];
this.size = size;
}
void resize(int size) {
int length = literals.length;
if (size < length) {
Literal literal[] = new Literal[size];
JsclInteger coef[] = new JsclInteger[size];
System.arraycopy(this.literals, length - size, literal, 0, size);
System.arraycopy(this.coefficients, length - size, coef, 0, size);
this.literals = literal;
this.coefficients = coef;
this.size = size;
}
}
public Expression add(@Nonnull Expression that) {
final Expression result = newInstance(size + that.size);
int i = result.size;
int thisI = this.size;
int thatI = that.size;
Literal thisLiteral = thisI > 0 ? this.literals[--thisI] : null;
Literal thatLiteral = thatI > 0 ? that.literals[--thatI] : null;
while (thisLiteral != null || thatLiteral != null) {
int c;
if (thisLiteral == null) {
c = 1;
} else if (thatLiteral == null) {
c = -1;
} else {
c = -thisLiteral.compareTo(thatLiteral);
}
if (c < 0) {
final JsclInteger thisCoefficient = this.coefficients[thisI];
--i;
result.literals[i] = thisLiteral;
result.coefficients[i] = thisCoefficient;
thisLiteral = thisI > 0 ? literals[--thisI] : null;
} else if (c > 0) {
JsclInteger en = that.coefficients[thatI];
--i;
result.literals[i] = thatLiteral;
result.coefficients[i] = en;
thatLiteral = thatI > 0 ? that.literals[--thatI] : null;
} else {
JsclInteger sum = coefficients[thisI].add(that.coefficients[thatI]);
if (sum.signum() != 0) {
--i;
result.literals[i] = thisLiteral;
result.coefficients[i] = sum;
}
thisLiteral = thisI > 0 ? literals[--thisI] : null;
thatLiteral = thatI > 0 ? that.literals[--thatI] : null;
}
}
result.resize(result.size - i);
return result;
}
@Nonnull
public Generic add(@Nonnull Generic that) {
if (that instanceof Expression) {
return add((Expression) that);
} else if (that instanceof JsclInteger || that instanceof Rational || that instanceof NumericWrapper) {
return add(valueOf(that));
} else {
return that.valueOf(this).add(that);
}
}
public Expression subtract(Expression expression) {
return multiplyAndAdd(Literal.newInstance(), JsclInteger.valueOf(-1), expression);
}
@Nonnull
public Generic subtract(@Nonnull Generic that) {
if (that instanceof Expression) {
return subtract((Expression) that);
} else if (that instanceof JsclInteger || that instanceof Rational || that instanceof NumericWrapper) {
return subtract(valueOf(that));
} else {
return that.valueOf(this).subtract(that);
}
}
Expression multiplyAndAdd(@Nonnull Literal literal, @Nonnull JsclInteger coefficient, @Nonnull Expression that) {
if (coefficient.signum() == 0) return this;
final Expression result = newInstance(size + that.size);
int i = result.size;
int thisI = this.size;
int thatI = that.size;
Literal thisLiteral = thisI > 0 ? literals[--thisI] : null;
Literal thatLiteral = thatI > 0 ? that.literals[--thatI].multiply(literal) : null;
while (thisLiteral != null || thatLiteral != null) {
int c = thisLiteral == null ? 1 : (thatLiteral == null ? -1 : -thisLiteral.compareTo(thatLiteral));
if (c < 0) {
JsclInteger en = coefficients[thisI];
--i;
result.literals[i] = thisLiteral;
result.coefficients[i] = en;
thisLiteral = thisI > 0 ? literals[--thisI] : null;
} else if (c > 0) {
JsclInteger en = that.coefficients[thatI].multiply(coefficient);
--i;
result.literals[i] = thatLiteral;
result.coefficients[i] = en;
thatLiteral = thatI > 0 ? that.literals[--thatI].multiply(literal) : null;
} else {
JsclInteger en = coefficients[thisI].add(that.coefficients[thatI].multiply(coefficient));
if (en.signum() != 0) {
--i;
result.literals[i] = thisLiteral;
result.coefficients[i] = en;
}
thisLiteral = thisI > 0 ? literals[--thisI] : null;
thatLiteral = thatI > 0 ? that.literals[--thatI].multiply(literal) : null;
}
}
result.resize(result.size - i);
return result;
}
public Expression multiply(Expression expression) {
Expression result = newInstance(0);
for (int i = 0; i < size; i++) {
result = result.multiplyAndAdd(literals[i], coefficients[i], expression);
}
return result;
}
@Nonnull
public Generic multiply(@Nonnull Generic that) {
if (that instanceof Expression) {
return multiply((Expression) that);
} else if (that instanceof JsclInteger || that instanceof Rational || that instanceof NumericWrapper) {
return multiply(valueOf(that));
} else {
return that.multiply(this);
}
}
@Nonnull
public Generic divide(@Nonnull Generic that) throws NotDivisibleException {
Generic a[] = divideAndRemainder(that);
if (a[1].signum() == 0) return a[0];
else throw new NotDivisibleException();
}
public Generic[] divideAndRemainder(Generic generic) throws ArithmeticException {
if (generic instanceof Expression) {
Expression ex = (Expression) generic;
Literal l1 = literalScm();
Literal l2 = ex.literalScm();
Literal l = l1.gcd(l2);
Variable va[] = l.variables();
if (va.length == 0) {
if (signum() == 0 && ex.signum() != 0) return new Generic[]{this, JsclInteger.valueOf(0)};
else try {
return divideAndRemainder(ex.integerValue());
} catch (NotIntegerException e) {
return new Generic[]{JsclInteger.valueOf(0), this};
}
} else {
Polynomial fact = Polynomial.factory(va[0]);
Polynomial p[] = fact.valueOf(this).divideAndRemainder(fact.valueOf(ex));
return new Generic[]{p[0].genericValue(), p[1].genericValue()};
}
} else if (generic instanceof JsclInteger) {
try {
Expression ex = newInstance(size);
for (int i = 0; i < size; i++) {
ex.literals[i] = literals[i];
ex.coefficients[i] = coefficients[i].divide((JsclInteger) generic);
}
return new Generic[]{ex, JsclInteger.valueOf(0)};
} catch (NotDivisibleException e) {
return new Generic[]{JsclInteger.valueOf(0), this};
}
} else if (generic instanceof Rational || generic instanceof NumericWrapper) {
return divideAndRemainder(valueOf(generic));
} else {
return generic.valueOf(this).divideAndRemainder(generic);
}
}
public Generic gcd(@Nonnull Generic generic) {
if (generic instanceof Expression) {
final Expression that = (Expression) generic;
final Literal thisL = this.literalScm();
final Literal thatL = that.literalScm();
final Literal gcdL = thisL.gcd(thatL);
final Variable vars[] = gcdL.variables();
if (vars.length == 0) {
if (signum() == 0) {
return that;
} else {
return this.gcd(that.gcd());
}
} else {
Polynomial p = Polynomial.factory(vars[0]);
return p.valueOf(this).gcd(p.valueOf(that)).genericValue();
}
} else if (generic instanceof JsclInteger) {
if (generic.signum() == 0) {
return this;
} else {
return this.gcd().gcd(generic);
}
} else if (generic instanceof Rational || generic instanceof NumericWrapper) {
return gcd(valueOf(generic));
} else {
return generic.valueOf(this).gcd(generic);
}
}
@Nonnull
public Generic gcd() {
JsclInteger result = JsclInteger.valueOf(0);
for (int i = size - 1; i >= 0; i--) {
result = result.gcd(coefficients[i]);
}
return result;
}
@Nonnull
public Literal literalScm() {
Literal result = Literal.newInstance();
for (int i = 0; i < size; i++) {
result = result.scm(literals[i]);
}
return result;
}
public Generic negate() {
return multiply(JsclInteger.valueOf(-1));
}
public int signum() {
return size == 0 ? 0 : coefficients[0].signum();
}
public int degree() {
return 0;
}
public Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException {
if (isPolynomial(variable)) {
return ((UnivariatePolynomial) Polynomial.factory(variable).valueOf(this)).antiderivative().genericValue();
} else {
try {
Variable v = variableValue();
try {
return v.antiDerivative(variable);
} catch (NotIntegrableException e) {
if (v instanceof Fraction) {
Generic g[] = ((Fraction) v).getParameters();
if (g[1].isConstant(variable)) {
return new Inverse(g[1]).selfExpand().multiply(g[0].antiDerivative(variable));
}
}
}
} catch (NotVariableException e) {
Generic sumElements[] = sumValue();
if (sumElements.length > 1) {
Generic result = JsclInteger.valueOf(0);
for (Generic sumElement : sumElements) {
result = result.add(sumElement.antiDerivative(variable));
}
return result;
} else {
final Generic products[] = sumElements[0].productValue();
Generic constantProduct = JsclInteger.valueOf(1);
Generic notConstantProduct = JsclInteger.valueOf(1);
for (Generic product : products) {
if (product.isConstant(variable)) {
constantProduct = constantProduct.multiply(product);
} else {
notConstantProduct = notConstantProduct.multiply(product);
}
}
if (constantProduct.compareTo(JsclInteger.valueOf(1)) != 0) {
return constantProduct.multiply(notConstantProduct.antiDerivative(variable));
}
}
}
}
throw new NotIntegrableException(this);
}
public Generic derivative(@Nonnull Variable variable) {
Generic s = JsclInteger.valueOf(0);
Literal l = literalScm();
int n = l.size();
for (int i = 0; i < n; i++) {
Variable v = l.getVariable(i);
Generic a = ((UnivariatePolynomial) Polynomial.factory(v).valueOf(this)).derivative(variable).genericValue();
s = s.add(a);
}
return s;
}
public Generic substitute(@Nonnull final Variable variable, final Generic generic) {
final Map<Variable, Generic> content = literalScm().content(new Converter<Variable, Generic>() {
@Nonnull
public Generic convert(@Nonnull Variable v) {
return v.substitute(variable, generic);
}
});
return substitute(content);
}
@Nonnull
private Generic substitute(@Nonnull Map<Variable, Generic> content) {
// sum = sumElement_0 + sumElement_1 + ... + sumElement_size
Generic sum = JsclInteger.ZERO;
for (int i = 0; i < size; i++) {
final Literal literal = literals[i];
// sumElement = variable_1 ^ power_1 * variable_2 ^ power_2 * ... * variable_size ^ power_size
Generic sumElement = coefficients[i];
for (int j = 0; j < literal.size(); j++) {
final Variable variable = literal.getVariable(j);
Generic b = content.get(variable).pow(literal.getPower(j));
if (Matrix.isMatrixProduct(sumElement, b)) {
throw new ArithmeticException("Should not be matrix!");
}
sumElement = sumElement.multiply(b);
}
sum = sum.add(sumElement);
}
return sum;
}
public Generic expand() {
return substitute(literalScm().content(EXPAND_CONVERTER));
}
public Generic factorize() {
return Factorization.compute(substitute(literalScm().content(FACTORIZE_CONVERTER)));
}
public Generic elementary() {
return substitute(literalScm().content(ELEMENTARY_CONVERTER));
}
public Generic simplify() {
return Simplification.compute(this);
}
public Generic numeric() {
try {
return integerValue().numeric();
} catch (NotIntegerException ex) {
final Literal literal = literalScm();
final Map<Variable, Generic> content = literal.content(NUMERIC_CONVERTER);
return substitute(content);
}
}
@Nonnull
public Generic valueOf(@Nonnull Generic generic) {
final Expression result = newInstance(0);
result.init(generic);
return result;
}
@Nonnull
public Generic[] sumValue() {
final Generic result[] = new Generic[size];
for (int i = 0; i < result.length; i++) {
result[i] = valueOf(literals[i], coefficients[i]);
}
return result;
}
@Nonnull
public Generic[] productValue() throws NotProductException {
if (size == 0) {
return new Generic[]{JsclInteger.valueOf(0)};
} else if (size == 1) {
final Literal l = literals[0];
final JsclInteger k = coefficients[0];
Generic productElements[] = l.productValue();
if (k.compareTo(JsclInteger.valueOf(1)) == 0) {
return productElements;
} else {
final Generic result[] = new Generic[productElements.length + 1];
System.arraycopy(productElements, 0, result, 1, productElements.length);
result[0] = k;
return result;
}
} else {
throw new NotProductException();
}
}
public Power powerValue() throws NotPowerException {
if (size == 0) return new Power(JsclInteger.valueOf(0), 1);
else if (size == 1) {
Literal l = literals[0];
JsclInteger en = coefficients[0];
if (en.compareTo(JsclInteger.valueOf(1)) == 0) return l.powerValue();
else if (l.degree() == 0) return en.powerValue();
else throw new NotPowerException();
} else throw new NotPowerException();
}
public Expression expressionValue() throws NotExpressionException {
return this;
}
@Override
public boolean isInteger() {
try {
integerValue();
return true;
} catch (NotIntegerException e) {
return false;
}
}
public JsclInteger integerValue() throws NotIntegerException {
if (size == 0) {
return JsclInteger.valueOf(0);
} else if (size == 1) {
final Literal l = literals[0];
final JsclInteger c = coefficients[0];
if (l.degree() == 0) {
return c;
} else {
throw new NotIntegerException();
}
} else {
throw new NotIntegerException();
}
}
public Variable variableValue() throws NotVariableException {
if (size == 0) {
throw new NotVariableException();
} else if (size == 1) {
final Literal l = literals[0];
final JsclInteger c = coefficients[0];
if (c.compareTo(JsclInteger.valueOf(1)) == 0) {
return l.variableValue();
} else {
throw new NotVariableException();
}
} else {
throw new NotVariableException();
}
}
public Variable[] variables() {
return literalScm().variables();
}
public boolean isPolynomial(@Nonnull Variable variable) {
boolean result = true;
final Literal l = literalScm();
for (int i = 0; i < l.size(); i++) {
final Variable v = l.getVariable(i);
if (!v.isConstant(variable) && !v.isIdentity(variable)) {
result = false;
break;
}
}
return result;
}
public boolean isConstant(@Nonnull Variable variable) {
Literal l = literalScm();
for (int i = 0; i < l.size(); i++) {
if (!l.getVariable(i).isConstant(variable)) {
return false;
}
}
return true;
}
public JsclVector grad(Variable variable[]) {
Generic v[] = new Generic[variable.length];
for (int i = 0; i < variable.length; i++) v[i] = derivative(variable[i]);
return new JsclVector(v);
}
public Generic laplacian(Variable variable[]) {
return grad(variable).divergence(variable);
}
public Generic dalembertian(Variable variable[]) {
Generic a = derivative(variable[0]).derivative(variable[0]);
for (int i = 1; i < 4; i++) a = a.subtract(derivative(variable[i]).derivative(variable[i]));
return a;
}
public int compareTo(Expression expression) {
int i1 = size;
int i2 = expression.size;
Literal l1 = i1 == 0 ? null : literals[--i1];
Literal l2 = i2 == 0 ? null : expression.literals[--i2];
while (l1 != null || l2 != null) {
int c = l1 == null ? -1 : (l2 == null ? 1 : l1.compareTo(l2));
if (c < 0) return -1;
else if (c > 0) return 1;
else {
c = coefficients[i1].compareTo(expression.coefficients[i2]);
if (c < 0) return -1;
else if (c > 0) return 1;
l1 = i1 == 0 ? null : literals[--i1];
l2 = i2 == 0 ? null : expression.literals[--i2];
}
}
return 0;
}
public int compareTo(@Nonnull Generic generic) {
if (generic instanceof Expression) {
return compareTo((Expression) generic);
} else if (generic instanceof JsclInteger || generic instanceof Rational || generic instanceof NumericWrapper) {
return compareTo(valueOf(generic));
} else {
return generic.valueOf(this).compareTo(generic);
}
}
void init(Literal lit, JsclInteger integer) {
if (integer.signum() != 0) {
init(1);
literals[0] = lit;
coefficients[0] = integer;
} else init(0);
}
void init(Expression expression) {
init(expression.size);
System.arraycopy(expression.literals, 0, literals, 0, size);
System.arraycopy(expression.coefficients, 0, coefficients, 0, size);
}
void init(JsclInteger integer) {
init(Literal.newInstance(), integer);
}
void init(Rational rational) {
try {
init(Literal.newInstance(), rational.integerValue());
} catch (NotIntegerException e) {
init(Literal.valueOf(rational.variableValue()), JsclInteger.valueOf(1));
}
}
Expression init(@Nonnull Generic generic) {
if (generic instanceof Expression) {
init((Expression) generic);
} else if (generic instanceof JsclInteger) {
init((JsclInteger) generic);
} else if (generic instanceof NumericWrapper) {
init((NumericWrapper) generic);
} else if (generic instanceof Rational) {
init((Rational) generic);
} else throw new ArithmeticException("Could not initialize expression with " + generic.getClass());
return this;
}
public String toString() {
final StringBuilder result = new StringBuilder();
if (signum() == 0) {
result.append("0");
}
// result = coef[0] * literal[0] + coef[1] * literal[1] + ... +
for (int i = 0; i < size; i++) {
final Literal literal = literals[i];
final JsclInteger coefficient = coefficients[i];
if (coefficient.signum() > 0 && i > 0) {
result.append("+");
}
if (literal.degree() == 0) {
result.append(coefficient);
} else {
if (coefficient.abs().compareTo(JsclInteger.valueOf(1)) == 0) {
if (coefficient.signum() < 0) {
result.append("-");
}
} else {
result.append(coefficient).append("*");
}
result.append(literal);
}
}
return result.toString();
}
public String toJava() {
final StringBuilder result = new StringBuilder();
if (signum() == 0) {
result.append("JsclDouble.valueOf(0)");
}
for (int i = 0; i < size; i++) {
Literal l = literals[i];
JsclInteger en = coefficients[i];
if (i > 0) {
if (en.signum() < 0) {
result.append(".subtract(");
en = (JsclInteger) en.negate();
} else result.append(".add(");
}
if (l.degree() == 0) result.append(en.toJava());
else {
if (en.abs().compareTo(JsclInteger.valueOf(1)) == 0) {
if (en.signum() > 0) result.append(l.toJava());
else if (en.signum() < 0) result.append(l.toJava()).append(".negate()");
} else result.append(en.toJava()).append(".multiply(").append(l.toJava()).append(")");
}
if (i > 0) result.append(")");
}
return result.toString();
}
public void toMathML(MathML element, @Nullable Object data) {
MathML e1 = element.element("mrow");
if (signum() == 0) {
MathML e2 = element.element("mn");
e2.appendChild(element.text("0"));
e1.appendChild(e2);
}
for (int i = 0; i < size; i++) {
Literal l = literals[i];
JsclInteger en = coefficients[i];
if (en.signum() > 0 && i > 0) {
MathML e2 = element.element("mo");
e2.appendChild(element.text("+"));
e1.appendChild(e2);
}
if (l.degree() == 0) separateSign(e1, en);
else {
if (en.abs().compareTo(JsclInteger.valueOf(1)) == 0) {
if (en.signum() < 0) {
MathML e2 = element.element("mo");
e2.appendChild(element.text("-"));
e1.appendChild(e2);
}
} else separateSign(e1, en);
l.toMathML(e1, null);
}
}
element.appendChild(e1);
}
@Nonnull
@Override
public Set<? extends Constant> getConstants() {
final Set<Constant> result = new HashSet<Constant>();
for (Literal literal : literals) {
for (Variable variable : literal.variables()) {
result.addAll(variable.getConstants());
}
}
return result;
}
@Nonnull
private Expression newInstance(int n) {
return new Expression(n);
}
}

View File

@ -0,0 +1,60 @@
package jscl.math;
import jscl.mathml.MathML;
import javax.annotation.Nonnull;
public class ExpressionVariable extends GenericVariable {
public ExpressionVariable(Generic generic) {
super(generic);
}
public Generic substitute(Variable variable, Generic generic) {
if (isIdentity(variable)) return generic;
else return content.substitute(variable, generic);
}
public Generic elementary() {
return content.elementary();
}
public Generic simplify() {
return content.simplify();
}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("(").append(content).append(")");
return buffer.toString();
}
public String toJava() {
StringBuffer buffer = new StringBuffer();
buffer.append("(").append(content.toJava()).append(")");
return buffer.toString();
}
public void toMathML(MathML element, Object data) {
int exponent = data instanceof Integer ? ((Integer) data).intValue() : 1;
if (exponent == 1) bodyToMathML(element);
else {
MathML e1 = element.element("msup");
bodyToMathML(e1);
MathML e2 = element.element("mn");
e2.appendChild(element.text(String.valueOf(exponent)));
e1.appendChild(e2);
element.appendChild(e1);
}
}
void bodyToMathML(MathML element) {
MathML e1 = element.element("mfenced");
content.toMathML(e1, null);
element.appendChild(e1);
}
@Nonnull
public Variable newInstance() {
return new ExpressionVariable(null);
}
}

View File

@ -0,0 +1,298 @@
package jscl.math;
import jscl.math.polynomial.Basis;
import jscl.math.polynomial.Monomial;
import jscl.math.polynomial.Ordering;
import jscl.math.polynomial.Polynomial;
import jscl.util.ArrayComparator;
import jscl.util.ArrayUtils;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Factorization {
private static final String ter = "t";
Polynomial factory;
Generic result;
Factorization(Polynomial factory) {
this.factory = factory;
}
public static Generic compute(Generic generic) {
try {
return GenericVariable.content(factorize(generic.integerValue()));
} catch (NotIntegerException e) {
Factorization f = new Factorization(Polynomial.factory(generic.variables(), Monomial.iteratorOrdering, -1));
f.computeValue(generic);
return f.getValue();
}
}
static Generic factorize(JsclInteger integer) {
Generic n[] = integer.gcdAndNormalize();
Generic s = n[1];
Generic a = JsclInteger.valueOf(1);
Generic p = JsclInteger.valueOf(2);
while (s.compareTo(JsclInteger.valueOf(1)) > 0) {
Generic q[] = s.divideAndRemainder(p);
if (q[0].compareTo(p) < 0) {
p = s;
q = s.divideAndRemainder(p);
}
if (q[1].signum() == 0) {
a = a.multiply(expression(p, true));
s = q[0];
} else p = p.add(JsclInteger.valueOf(1));
}
return a.multiply(n[0]);
}
static Polynomial[] remainder(Polynomial s, Polynomial p, Generic t[]) {
Polynomial zero = s.valueOf(JsclInteger.valueOf(0));
Generic a[] = Basis.augment(t, s.remainderUpToCoefficient(p).elements());
Variable unk[] = Basis.augmentUnknown(new Variable[]{}, p.elements());
{
Variable u = unk[unk.length - 1];
System.arraycopy(unk, 0, unk, 1, unk.length - 1);
unk[0] = u;
}
Generic be[][] = Linearization.compute(Basis.compute(a, unk, Monomial.lexicographic, 0, Basis.DEGREE).elements(), unk);
for (int i = 0; i < be.length; i++) {
Polynomial r = substitute(p, be[i], unk);
try {
return new Polynomial[]{zero, r, s.divide(r)};
} catch (NotDivisibleException e) {
}
}
return new Polynomial[]{s, zero, zero};
}
static Polynomial substitute(Polynomial p, Generic a[], Variable unk[]) {
Generic s[] = new Generic[]{p.genericValue()};
return p.valueOf(Basis.compute(Basis.augment(a, s), Basis.augmentUnknown(unk, s)).elements()[0]);
}
static Polynomial polynomial(Polynomial s, Monomial monomial[]) {
Polynomial p = s.valueOf(JsclInteger.valueOf(0));
Iterator it = monomial[1].iterator(monomial[0]);
for (int i = 0; it.hasNext(); i++) {
Monomial m = (Monomial) it.next();
Variable t = it.hasNext() ? new TechnicalVariable(ter, new int[]{i}) : new TechnicalVariable(ter);
p = p.add(p.valueOf(m).multiply(t.expressionValue()));
}
return p;
}
static Generic[] terminator(Polynomial polynomial) {
Generic t[] = new Generic[2];
t[1] = terminator(polynomial.head().coef().abs(), new TechnicalVariable(ter), false);
t[0] = terminator(polynomial.tail().coef(), new TechnicalVariable(ter, new int[]{0}), true);
return t;
}
static Generic terminator(Generic generic, Variable var, boolean tail) {
Generic x = var.expressionValue();
Generic a = JsclInteger.valueOf(1);
Iterator it = IntegerDivisor.create(generic.integerValue());
while (it.hasNext()) {
Generic s = (Generic) it.next();
a = a.multiply(x.subtract(s));
if (!tail) a = a.multiply(x.add(s));
}
return a;
}
static Generic expression(Generic generic) {
return expression(generic, false);
}
static Generic expression(Generic generic, boolean integer) {
if (generic.compareTo(JsclInteger.valueOf(1)) == 0) return generic;
else return GenericVariable.valueOf(generic, integer).expressionValue();
}
static String toString(Monomial monomial[]) {
return "{" + monomial[0] + ", " + monomial[1] + "}";
}
void computeValue(Generic generic) {
Debug.println("factorization");
Polynomial n[] = factory.valueOf(generic).gcdAndNormalize();
Monomial m = n[1].monomialGcd();
Polynomial s = n[1].divide(m);
Generic a = JsclInteger.valueOf(1);
Divisor d[] = new Divisor[2];
Monomial p[] = new Monomial[2];
Monomial q[] = new Monomial[2];
d[1] = new Divisor(s.head().monomial());
loop:
while (d[1].hasNext()) {
p[1] = (Monomial) d[1].next();
q[1] = d[1].complementary();
d[0] = new Divisor(s.tail().monomial());
while (d[0].hasNext()) {
p[0] = (Monomial) d[0].next();
q[0] = d[0].complementary();
if (p[1].compareTo(p[0]) <= 0) continue loop;
Debug.println(toString(p) + " * " + toString(q) + " = " + s);
if (ArrayComparator.comparator.compare(q, p) < 0) {
a = a.multiply(expression(s.genericValue()));
break loop;
} else {
Debug.increment();
Polynomial r[] = remainder(s, polynomial(s, p), terminator(s));
Debug.decrement();
if (r[0].signum() == 0) {
a = a.multiply(expression(r[1].genericValue()));
s = r[2];
d[1].divide();
d[0].divide();
continue loop;
}
}
}
}
result = a.multiply(n[0].multiply(m).genericValue());
}
Generic getValue() {
return GenericVariable.content(result, true);
}
}
class Linearization {
Variable unknown[];
List result = new ArrayList();
Linearization(Variable unknown[]) {
this.unknown = unknown;
}
static Generic[][] compute(Generic generic[], Variable unknown[]) {
Linearization l = new Linearization(unknown);
Debug.println("linearization");
Debug.increment();
l.process(generic);
Debug.decrement();
return l.getValue();
}
static Polynomial[] linearize(Polynomial polynomial, Variable variable) {
List l = new ArrayList();
Generic x = variable.expressionValue();
Polynomial s = polynomial;
try {
Polynomial r = s.valueOf(x);
s = s.divide(r);
l.add(r);
while (true) s = s.divide(r);
} catch (NotDivisibleException e) {
}
IntegerDivisor d[] = new IntegerDivisor[2];
Generic p[] = new Generic[2];
Generic q[] = new Generic[2];
d[1] = IntegerDivisor.create(JsclInteger.valueOf(1));
loop:
while (d[1].hasNext()) {
p[1] = (Generic) d[1].next();
q[1] = d[1].integer(d[1].complementary());
d[0] = IntegerDivisor.create(s.tail().coef().integerValue());
while (d[0].hasNext()) {
p[0] = (Generic) d[0].next();
q[0] = d[0].integer(d[0].complementary());
if (ArrayComparator.comparator.compare(q, p) < 0) break loop;
for (int i = 0; i < 2; i++) {
Polynomial r = s.valueOf(i == 0 ? p[1].multiply(x).subtract(p[0]) : p[1].multiply(x).add(p[0]));
for (boolean flag = true; true; flag = false) {
try {
s = s.divide(r);
} catch (NotDivisibleException e) {
break;
}
d[1].divide();
d[0].divide();
if (flag) l.add(r);
}
}
}
}
return (Polynomial[]) ArrayUtils.toArray(l, new Polynomial[l.size()]);
}
void process(Generic generic[]) {
boolean flag = true;
for (int i = 0; i < generic.length; i++) {
Generic s = generic[i];
Variable va[] = s.variables();
if (va.length == 1) {
Variable t = va[0];
Polynomial p = Polynomial.factory(t).valueOf(s);
if (p.degree() > 1) {
flag = false;
Polynomial r[] = linearize(p, t);
for (int j = 0; j < r.length; j++) {
process(Basis.compute(Basis.augment(new Generic[]{r[j].genericValue()}, generic), unknown).elements());
}
}
} else flag = false;
}
if (flag) result.add(generic);
}
Generic[][] getValue() {
return (Generic[][]) ArrayUtils.toArray(result, new Generic[result.size()][]);
}
}
class Divisor implements Iterator {
Monomial monomial;
Monomial current;
Iterator iterator;
Divisor(Monomial monomial) {
this.monomial = monomial;
iterator = monomial.divisor();
}
Monomial complementary() {
return monomial.divide(current);
}
void divide() {
monomial = complementary();
iterator = monomial.divisor(current);
}
public boolean hasNext() {
return iterator.hasNext();
}
public Object next() {
return current = (Monomial) iterator.next();
}
public void remove() {
throw new UnsupportedOperationException();
}
}
class IntegerDivisor extends Divisor {
IntegerDivisor(Generic generic, Variable unknown[], Ordering ordering) {
super(Polynomial.factory(unknown, ordering).valueOf(generic).head().monomial());
}
static IntegerDivisor create(JsclInteger integer) {
Generic a = Factorization.factorize(integer);
return new IntegerDivisor(a, a.variables(), Monomial.iteratorOrdering);
}
public Object next() {
return integer((Monomial) super.next());
}
Generic integer(Monomial monomial) {
return Expression.valueOf(Literal.valueOf(monomial)).expand();
}
}

View File

@ -0,0 +1,4 @@
package jscl.math;
public interface Field {
}

View File

@ -0,0 +1,189 @@
package jscl.math;
import jscl.math.function.Constant;
import jscl.mathml.MathML;
import jscl.text.ParserUtils;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Set;
public abstract class Generic implements Arithmetic<Generic>, Comparable {
@Nonnull
public Generic subtract(@Nonnull Generic that) {
return add(that.negate());
}
public boolean multiple(Generic generic) throws ArithmeticException {
return remainder(generic).signum() == 0;
}
/* public Arithmetic add(@Nonnull Arithmetic arithmetic) {
return add((Generic)arithmetic);
}
public Arithmetic subtract(@Nonnull Arithmetic arithmetic) {
return subtract((Generic)arithmetic);
}
public Arithmetic multiply(@Nonnull Arithmetic arithmetic) {
return multiply((Generic)arithmetic);
}
public Generic divide(@Nonnull Arithmetic arithmetic) throws ArithmeticException {
return divide((Generic)arithmetic);
}*/
public Generic[] divideAndRemainder(Generic generic) {
try {
return new Generic[]{divide(generic), JsclInteger.valueOf(0)};
} catch (NotDivisibleException e) {
return new Generic[]{JsclInteger.valueOf(0), this};
}
}
public Generic remainder(Generic generic) throws ArithmeticException {
return divideAndRemainder(generic)[1];
}
public Generic inverse() {
return JsclInteger.valueOf(1).divide(this);
}
public abstract Generic gcd(@Nonnull Generic generic);
public Generic scm(Generic generic) {
return divide(gcd(generic)).multiply(generic);
}
@Nonnull
protected abstract Generic gcd();
public Generic[] gcdAndNormalize() {
Generic gcd = gcd();
if (gcd.signum() == 0) {
return new Generic[]{gcd, this};
}
if (gcd.signum() != signum()) {
gcd = gcd.negate();
}
return new Generic[]{gcd, divide(gcd)};
}
@SuppressWarnings({"UnusedDeclaration"})
public Generic normalize() {
return gcdAndNormalize()[1];
}
public Generic pow(int exponent) {
assert exponent >= 0;
Generic result = JsclInteger.valueOf(1);
for (int i = 0; i < exponent; i++) {
ParserUtils.checkInterruption();
result = result.multiply(this);
}
return result;
}
public Generic abs() {
return signum() < 0 ? negate() : this;
}
public abstract Generic negate();
public abstract int signum();
public abstract int degree();
// public abstract Generic mod(Generic generic);
// public abstract Generic modPow(Generic exponent, Generic generic);
// public abstract Generic modInverse(Generic generic);
// public abstract boolean isProbablePrime(int certainty);
public abstract Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException;
public abstract Generic derivative(@Nonnull Variable variable);
public abstract Generic substitute(@Nonnull Variable variable, Generic generic);
public abstract Generic expand();
public abstract Generic factorize();
public abstract Generic elementary();
public abstract Generic simplify();
public abstract Generic numeric();
public abstract Generic valueOf(Generic generic);
public abstract Generic[] sumValue();
public abstract Generic[] productValue() throws NotProductException;
public abstract Power powerValue() throws NotPowerException;
public abstract Expression expressionValue() throws NotExpressionException;
public abstract boolean isInteger();
public abstract JsclInteger integerValue() throws NotIntegerException;
public abstract Variable variableValue() throws NotVariableException;
public abstract Variable[] variables();
public abstract boolean isPolynomial(@Nonnull Variable variable);
public abstract boolean isConstant(@Nonnull Variable variable);
public boolean isIdentity(@Nonnull Variable variable) {
try {
return variableValue().isIdentity(variable);
} catch (NotVariableException e) {
return false;
}
}
public abstract int compareTo(Generic generic);
public int compareTo(Object o) {
return compareTo((Generic) o);
}
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o instanceof Generic) {
final Generic that = ((Generic) o);
return compareTo(that) == 0;
}
return false;
}
public abstract String toJava();
public String toMathML() {
MathML document = new MathML("math", "-//W3C//DTD MathML 2.0//EN", "http://www.w3.org/TR/MathML2/dtd/mathml2.dtd");
MathML e = document.element("math");
toMathML(e, null);
return e.toString();
}
public abstract void toMathML(MathML element, @Nullable Object data);
@Nonnull
public abstract Set<? extends Constant> getConstants();
}

View File

@ -0,0 +1,118 @@
package jscl.math;
import jscl.math.function.Constant;
import jscl.mathml.MathML;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Set;
public abstract class GenericVariable extends Variable {
Generic content;
GenericVariable(Generic generic) {
super("");
content = generic;
}
public static Generic content(Generic generic) {
return content(generic, false);
}
public static Generic content(Generic generic, boolean expression) {
try {
Variable v = generic.variableValue();
if (expression) {
if (v instanceof ExpressionVariable) generic = ((ExpressionVariable) v).content;
} else {
if (v instanceof GenericVariable) generic = ((GenericVariable) v).content;
}
} catch (NotVariableException e) {
}
return generic;
}
public static GenericVariable valueOf(Generic generic) {
return valueOf(generic, false);
}
public static GenericVariable valueOf(Generic generic, boolean integer) {
if (integer) return new IntegerVariable(generic);
else return new ExpressionVariable(generic);
}
public Generic antiDerivative(Variable variable) throws NotIntegrableException {
return content.antiDerivative(variable);
}
@Nonnull
public Generic derivative(Variable variable) {
return content.derivative(variable);
}
public Generic substitute(Variable variable, Generic generic) {
GenericVariable v = (GenericVariable) newInstance();
v.content = content.substitute(variable, generic);
if (v.isIdentity(variable)) return generic;
else return v.expressionValue();
}
public Generic expand() {
return content.expand();
}
public Generic factorize() {
GenericVariable v = (GenericVariable) newInstance();
v.content = content.factorize();
return v.expressionValue();
}
public Generic elementary() {
GenericVariable v = (GenericVariable) newInstance();
v.content = content.elementary();
return v.expressionValue();
}
public Generic simplify() {
GenericVariable v = (GenericVariable) newInstance();
v.content = content.simplify();
return v.expressionValue();
}
public Generic numeric() {
return content.numeric();
}
public boolean isConstant(Variable variable) {
return content.isConstant(variable);
}
public int compareTo(Variable variable) {
if (this == variable) return 0;
int c = comparator.compare(this, variable);
if (c < 0) return -1;
else if (c > 0) return 1;
else {
GenericVariable v = (GenericVariable) variable;
return content.compareTo(v.content);
}
}
public String toString() {
return content.toString();
}
public String toJava() {
return content.toJava();
}
public void toMathML(MathML element, @Nullable Object data) {
content.toMathML(element, data);
}
@Nonnull
@Override
public Set<? extends Constant> getConstants() {
return content.getConstants();
}
}

View File

@ -0,0 +1,60 @@
package jscl.math;
import jscl.mathml.MathML;
import javax.annotation.Nonnull;
class IntegerVariable extends GenericVariable {
IntegerVariable(Generic generic) {
super(generic);
}
public Generic substitute(Variable variable, Generic generic) {
if (isIdentity(variable)) return generic;
else return content.substitute(variable, generic);
}
public Generic elementary() {
return content.elementary();
}
public Generic simplify() {
return content.simplify();
}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("(").append(content).append(")");
return buffer.toString();
}
public String toJava() {
StringBuffer buffer = new StringBuffer();
buffer.append("(").append(content.toJava()).append(")");
return buffer.toString();
}
public void toMathML(MathML element, Object data) {
int exponent = data instanceof Integer ? ((Integer) data).intValue() : 1;
if (exponent == 1) bodyToMathML(element);
else {
MathML e1 = element.element("msup");
bodyToMathML(e1);
MathML e2 = element.element("mn");
e2.appendChild(element.text(String.valueOf(exponent)));
e1.appendChild(e2);
element.appendChild(e1);
}
}
void bodyToMathML(MathML element) {
MathML e1 = element.element("mfenced");
content.toMathML(e1, null);
element.appendChild(e1);
}
@Nonnull
public Variable newInstance() {
return new IntegerVariable(null);
}
}

View File

@ -0,0 +1,15 @@
package jscl.math;
public class JsclBoolean extends ModularInteger {
public static final JsclBoolean factory = new JsclBoolean(0);
private static final JsclBoolean zero = factory;
private static final JsclBoolean one = new JsclBoolean(1);
public JsclBoolean(long content) {
super(content, 2);
}
protected ModularInteger newinstance(long content) {
return content % 2 == 0 ? zero : one;
}
}

View File

@ -0,0 +1,367 @@
package jscl.math;
import jscl.JsclMathEngine;
import jscl.math.function.Constant;
import jscl.mathml.MathML;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.math.BigInteger;
import java.util.Collections;
import java.util.Set;
public final class JsclInteger extends Generic {
public static final JsclInteger factory = new JsclInteger(BigInteger.valueOf(0));
public static final JsclInteger ZERO = new JsclInteger(BigInteger.valueOf(0));
public static final JsclInteger ONE = new JsclInteger(BigInteger.valueOf(1));
private final BigInteger content;
public JsclInteger(BigInteger content) {
this.content = content;
}
public static JsclInteger valueOf(long val) {
switch ((int) val) {
case 0:
return ZERO;
case 1:
return ONE;
default:
return new JsclInteger(BigInteger.valueOf(val));
}
}
public static JsclInteger valueOf(String str) {
return new JsclInteger(new BigInteger(str));
}
public BigInteger content() {
return content;
}
public JsclInteger add(JsclInteger integer) {
return new JsclInteger(content.add(integer.content));
}
@Nonnull
public Generic add(@Nonnull Generic that) {
if (that instanceof JsclInteger) {
return add((JsclInteger) that);
} else {
return that.valueOf(this).add(that);
}
}
public JsclInteger subtract(JsclInteger integer) {
return new JsclInteger(content.subtract(integer.content));
}
@Nonnull
public Generic subtract(@Nonnull Generic that) {
if (that instanceof JsclInteger) {
return subtract((JsclInteger) that);
} else {
return that.valueOf(this).subtract(that);
}
}
public JsclInteger multiply(JsclInteger integer) {
return new JsclInteger(content.multiply(integer.content));
}
@Nonnull
public Generic multiply(@Nonnull Generic that) {
if (that instanceof JsclInteger) {
return multiply((JsclInteger) that);
} else {
return that.multiply(this);
}
}
public JsclInteger divide(@Nonnull JsclInteger that) {
JsclInteger e[] = divideAndRemainder(that);
if (e[1].signum() == 0) {
return e[0];
} else {
throw new NotDivisibleException();
}
}
@Nonnull
public Generic divide(@Nonnull Generic that) throws NotDivisibleException {
if (that instanceof JsclInteger) {
return divide((JsclInteger) that);
} else {
return that.valueOf(this).divide(that);
}
}
@Nonnull
private JsclInteger[] divideAndRemainder(@Nonnull JsclInteger that) {
try {
final BigInteger result[] = content.divideAndRemainder(that.content);
return new JsclInteger[]{new JsclInteger(result[0]), new JsclInteger(result[1])};
} catch (ArithmeticException e) {
throw new NotDivisibleException();
}
}
public Generic[] divideAndRemainder(@Nonnull Generic that) {
if (that instanceof JsclInteger) {
return divideAndRemainder((JsclInteger) that);
} else {
return that.valueOf(this).divideAndRemainder(that);
}
}
public JsclInteger remainder(JsclInteger integer) throws ArithmeticException {
return new JsclInteger(content.remainder(integer.content));
}
public Generic remainder(Generic generic) throws ArithmeticException {
if (generic instanceof JsclInteger) {
return remainder((JsclInteger) generic);
} else {
return generic.valueOf(this).remainder(generic);
}
}
@Nonnull
public JsclInteger gcd(@Nonnull JsclInteger integer) {
return new JsclInteger(content.gcd(integer.content));
}
public Generic gcd(@Nonnull Generic generic) {
if (generic instanceof JsclInteger) {
return gcd((JsclInteger) generic);
} else {
return generic.valueOf(this).gcd(generic);
}
}
@Nonnull
public Generic gcd() {
return new JsclInteger(BigInteger.valueOf(signum()));
}
public Generic pow(int exponent) {
return new JsclInteger(content.pow(exponent));
}
public Generic negate() {
return new JsclInteger(content.negate());
}
public int signum() {
return content.signum();
}
public int degree() {
return 0;
}
public JsclInteger mod(JsclInteger integer) {
return new JsclInteger(content.mod(integer.content));
}
public JsclInteger modPow(JsclInteger exponent, JsclInteger integer) {
return new JsclInteger(content.modPow(exponent.content, integer.content));
}
public JsclInteger modInverse(JsclInteger integer) {
return new JsclInteger(content.modInverse(integer.content));
}
public JsclInteger phi() {
if (signum() == 0) return this;
Generic a = factorize();
Generic p[] = a.productValue();
Generic s = JsclInteger.valueOf(1);
for (int i = 0; i < p.length; i++) {
Power o = p[i].powerValue();
Generic q = o.value(true);
int c = o.exponent();
s = s.multiply(q.subtract(JsclInteger.valueOf(1)).multiply(q.pow(c - 1)));
}
return s.integerValue();
}
public JsclInteger[] primitiveRoots() {
JsclInteger phi = phi();
Generic a = phi.factorize();
Generic p[] = a.productValue();
JsclInteger d[] = new JsclInteger[p.length];
for (int i = 0; i < p.length; i++) {
d[i] = phi.divide(p[i].powerValue().value(true).integerValue());
}
int k = 0;
JsclInteger n = this;
JsclInteger m = JsclInteger.valueOf(1);
JsclInteger r[] = new JsclInteger[phi.phi().intValue()];
while (m.compareTo(n) < 0) {
boolean b = m.gcd(n).compareTo(JsclInteger.valueOf(1)) == 0;
for (int i = 0; i < d.length; i++) {
b = b && m.modPow(d[i], n).compareTo(JsclInteger.valueOf(1)) > 0;
}
if (b) r[k++] = m;
m = m.add(JsclInteger.valueOf(1));
}
return k > 0 ? r : new JsclInteger[0];
}
public JsclInteger sqrt() {
return nthrt(2);
}
public JsclInteger nthrt(int n) {
// return JsclInteger.valueOf((int)Math.pow((double)intValue(),1./n));
if (signum() == 0) {
return JsclInteger.valueOf(0);
} else if (signum() < 0) {
if (n % 2 == 0) {
throw new ArithmeticException("Could not calculate root of negative argument: " + this + " of odd order: " + n);
} else {
return (JsclInteger) ((JsclInteger) negate()).nthrt(n).negate();
}
} else {
Generic x0;
Generic x = this;
do {
x0 = x;
x = divideAndRemainder(x.pow(n - 1))[0].add(x.multiply(JsclInteger.valueOf(n - 1))).divideAndRemainder(JsclInteger.valueOf(n))[0];
} while (x.compareTo(x0) < 0);
return x0.integerValue();
}
}
public Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException {
return multiply(variable.expressionValue());
}
public Generic derivative(@Nonnull Variable variable) {
return JsclInteger.valueOf(0);
}
public Generic substitute(@Nonnull Variable variable, Generic generic) {
return this;
}
public Generic expand() {
return this;
}
public Generic factorize() {
return Factorization.compute(this);
}
public Generic elementary() {
return this;
}
public Generic simplify() {
return this;
}
public Generic numeric() {
return new NumericWrapper(this);
}
public Generic valueOf(Generic generic) {
return new JsclInteger(((JsclInteger) generic).content);
}
public Generic[] sumValue() {
if (content.signum() == 0) return new Generic[0];
else return new Generic[]{this};
}
public Generic[] productValue() throws NotProductException {
if (content.compareTo(BigInteger.valueOf(1)) == 0) return new Generic[0];
else return new Generic[]{this};
}
public Power powerValue() throws NotPowerException {
if (content.signum() < 0) throw new NotPowerException();
else return new Power(this, 1);
}
public Expression expressionValue() throws NotExpressionException {
return Expression.valueOf(this);
}
public JsclInteger integerValue() throws NotIntegerException {
return this;
}
@Override
public boolean isInteger() {
return true;
}
public Variable variableValue() throws NotVariableException {
throw new NotVariableException();
}
public Variable[] variables() {
return new Variable[0];
}
public boolean isPolynomial(@Nonnull Variable variable) {
return true;
}
public boolean isConstant(@Nonnull Variable variable) {
return true;
}
public int intValue() {
return content.intValue();
}
public int compareTo(JsclInteger integer) {
return content.compareTo(integer.content);
}
public int compareTo(Generic generic) {
if (generic instanceof JsclInteger) {
return compareTo((JsclInteger) generic);
} else {
return generic.valueOf(this).compareTo(generic);
}
}
public String toString() {
// todo serso: actually better way is to provide custom format() method for integers and not to convert integer to double
return JsclMathEngine.getInstance().format(this.content.doubleValue());
}
public String toJava() {
return "JsclDouble.valueOf(" + content + ")";
}
public void toMathML(MathML element, @Nullable Object data) {
int exponent = data instanceof Integer ? (Integer) data : 1;
if (exponent == 1) bodyToMathML(element);
else {
MathML e1 = element.element("msup");
bodyToMathML(e1);
MathML e2 = element.element("mn");
e2.appendChild(element.text(String.valueOf(exponent)));
e1.appendChild(e2);
element.appendChild(e1);
}
}
@Nonnull
@Override
public Set<? extends Constant> getConstants() {
return Collections.emptySet();
}
void bodyToMathML(MathML element) {
MathML e1 = element.element("mn");
e1.appendChild(element.text(String.valueOf(content)));
element.appendChild(e1);
}
}

View File

@ -0,0 +1,466 @@
package jscl.math;
import jscl.math.function.Conjugate;
import jscl.math.function.Constant;
import jscl.math.function.Fraction;
import jscl.mathml.MathML;
import jscl.util.ArrayComparator;
import javax.annotation.Nonnull;
import java.util.HashSet;
import java.util.Set;
public class JsclVector extends Generic {
@Nonnull
protected final Generic elements[];
protected final int rows;
public JsclVector(@Nonnull Generic elements[]) {
this.elements = elements;
this.rows = elements.length;
}
@Nonnull
public static JsclVector unity(int dimension) {
final JsclVector result = new JsclVector(new Generic[dimension]);
for (int i = 0; i < result.rows; i++) {
if (i == 0) {
result.elements[i] = JsclInteger.valueOf(1);
} else {
result.elements[i] = JsclInteger.valueOf(0);
}
}
return result;
}
@Nonnull
public Generic[] elements() {
return elements;
}
public JsclVector add(@Nonnull JsclVector vector) {
final JsclVector result = (JsclVector) newInstance();
for (int i = 0; i < rows; i++) {
result.elements[i] = elements[i].add(vector.elements[i]);
}
return result;
}
@Nonnull
public Generic add(@Nonnull Generic that) {
if (that instanceof JsclVector) {
return add((JsclVector) that);
} else {
return add(valueOf(that));
}
}
public JsclVector subtract(@Nonnull JsclVector vector) {
final JsclVector result = (JsclVector) newInstance();
for (int i = 0; i < rows; i++) {
result.elements[i] = elements[i].subtract(vector.elements[i]);
}
return result;
}
@Nonnull
public Generic subtract(@Nonnull Generic that) {
if (that instanceof JsclVector) {
return subtract((JsclVector) that);
} else {
return subtract(valueOf(that));
}
}
@Nonnull
public Generic multiply(@Nonnull Generic that) {
if (that instanceof JsclVector) {
return scalarProduct((JsclVector) that);
} else if (that instanceof Matrix) {
return ((Matrix) that).transpose().multiply(this);
} else {
final JsclVector result = (JsclVector) newInstance();
for (int i = 0; i < rows; i++) {
result.elements[i] = elements[i].multiply(that);
}
return result;
}
}
@Nonnull
public Generic divide(@Nonnull Generic that) throws NotDivisibleException {
if (that instanceof JsclVector) {
throw new ArithmeticException("Unable to divide vector by vector!");
} else if (that instanceof Matrix) {
return multiply(that.inverse());
} else {
final JsclVector result = (JsclVector) newInstance();
for (int i = 0; i < rows; i++) {
try {
result.elements[i] = elements[i].divide(that);
} catch (NotDivisibleException e) {
result.elements[i] = new Fraction(elements[i], that).selfExpand();
}
}
return result;
}
}
public Generic gcd(@Nonnull Generic generic) {
return null;
}
@Nonnull
public Generic gcd() {
return null;
}
public Generic negate() {
final JsclVector result = (JsclVector) newInstance();
for (int i = 0; i < rows; i++) {
result.elements[i] = elements[i].negate();
}
return result;
}
public int signum() {
for (int i = 0; i < rows; i++) {
int c = elements[i].signum();
if (c < 0) {
return -1;
} else if (c > 0) {
return 1;
}
}
return 0;
}
public int degree() {
return 0;
}
public Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException {
final JsclVector result = (JsclVector) newInstance();
for (int i = 0; i < rows; i++) {
result.elements[i] = elements[i].antiDerivative(variable);
}
return result;
}
public Generic derivative(@Nonnull Variable variable) {
final JsclVector result = (JsclVector) newInstance();
for (int i = 0; i < rows; i++) {
result.elements[i] = elements[i].derivative(variable);
}
return result;
}
public Generic substitute(@Nonnull Variable variable, Generic generic) {
final JsclVector result = (JsclVector) newInstance();
for (int i = 0; i < rows; i++) {
result.elements[i] = elements[i].substitute(variable, generic);
}
return result;
}
public Generic expand() {
JsclVector v = (JsclVector) newInstance();
for (int i = 0; i < rows; i++) v.elements[i] = elements[i].expand();
return v;
}
public Generic factorize() {
final JsclVector result = (JsclVector) newInstance();
for (int i = 0; i < rows; i++) {
result.elements[i] = elements[i].factorize();
}
return result;
}
public Generic elementary() {
final JsclVector result = (JsclVector) newInstance();
for (int i = 0; i < rows; i++) {
result.elements[i] = elements[i].elementary();
}
return result;
}
public Generic simplify() {
final JsclVector result = (JsclVector) newInstance();
for (int i = 0; i < rows; i++) {
result.elements[i] = elements[i].simplify();
}
return result;
}
public Generic numeric() {
return new NumericWrapper(this);
}
public Generic valueOf(@Nonnull Generic generic) {
if (generic instanceof JsclVector || generic instanceof Matrix) {
throw new ArithmeticException("Unable to create vector: vector of vectors or vector of matrices are forbidden!");
} else {
JsclVector v = (JsclVector) unity(rows).multiply(generic);
return newInstance(v.elements);
}
}
public Generic[] sumValue() {
return new Generic[]{this};
}
public Generic[] productValue() throws NotProductException {
return new Generic[]{this};
}
public Power powerValue() throws NotPowerException {
return new Power(this, 1);
}
public Expression expressionValue() throws NotExpressionException {
throw new NotExpressionException();
}
public JsclInteger integerValue() throws NotIntegerException {
throw new NotIntegerException();
}
@Override
public boolean isInteger() {
return false;
}
public Variable variableValue() throws NotVariableException {
throw new NotVariableException();
}
public Variable[] variables() {
return null;
}
public boolean isPolynomial(@Nonnull Variable variable) {
return false;
}
public boolean isConstant(@Nonnull Variable variable) {
return false;
}
public Generic magnitude2() {
return scalarProduct(this);
}
public Generic scalarProduct(@Nonnull JsclVector vector) {
Generic result = JsclInteger.valueOf(0);
for (int i = 0; i < rows; i++) {
result = result.add(elements[i].multiply(vector.elements[i]));
}
return result;
}
public JsclVector vectorProduct(@Nonnull JsclVector vector) {
final JsclVector result = (JsclVector) newInstance();
Generic m[][] = {
{JsclInteger.valueOf(0), elements[2].negate(), elements[1]},
{elements[2], JsclInteger.valueOf(0), elements[0].negate()},
{elements[1].negate(), elements[0], JsclInteger.valueOf(0)}
};
JsclVector v2 = (JsclVector) new Matrix(m).multiply(vector);
for (int i = 0; i < rows; i++) {
result.elements[i] = i < v2.rows ? v2.elements[i] : JsclInteger.valueOf(0);
}
return result;
}
public JsclVector complexProduct(JsclVector vector) {
return product(new Clifford(0, 1).operator(), vector);
}
public JsclVector quaternionProduct(JsclVector vector) {
return product(new Clifford(0, 2).operator(), vector);
}
public JsclVector geometricProduct(JsclVector vector, int algebra[]) {
return product(new Clifford(algebra == null ? new int[]{Clifford.log2e(rows), 0} : algebra).operator(), vector);
}
JsclVector product(int product[][], JsclVector vector) {
JsclVector v = (JsclVector) newInstance();
for (int i = 0; i < rows; i++) v.elements[i] = JsclInteger.valueOf(0);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < rows; j++) {
Generic a = elements[i].multiply(vector.elements[j]);
int k = Math.abs(product[i][j]) - 1;
v.elements[k] = v.elements[k].add(product[i][j] < 0 ? a.negate() : a);
}
}
return v;
}
public Generic divergence(Variable variable[]) {
Generic a = JsclInteger.valueOf(0);
for (int i = 0; i < rows; i++) a = a.add(elements[i].derivative(variable[i]));
return a;
}
public JsclVector curl(Variable variable[]) {
JsclVector v = (JsclVector) newInstance();
v.elements[0] = elements[2].derivative(variable[1]).subtract(elements[1].derivative(variable[2]));
v.elements[1] = elements[0].derivative(variable[2]).subtract(elements[2].derivative(variable[0]));
v.elements[2] = elements[1].derivative(variable[0]).subtract(elements[0].derivative(variable[1]));
for (int i = 3; i < rows; i++) v.elements[i] = elements[i];
return v;
}
public Matrix jacobian(Variable variable[]) {
Matrix m = new Matrix(new Generic[rows][variable.length]);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < variable.length; j++) {
m.elements[i][j] = elements[i].derivative(variable[j]);
}
}
return m;
}
public Generic del(Variable variable[], int algebra[]) {
return differential(new Clifford(algebra == null ? new int[]{Clifford.log2e(rows), 0} : algebra).operator(), variable);
}
JsclVector differential(int product[][], Variable variable[]) {
JsclVector v = (JsclVector) newInstance();
for (int i = 0; i < rows; i++) v.elements[i] = JsclInteger.valueOf(0);
int l = Clifford.log2e(rows);
for (int i = 1; i <= l; i++) {
for (int j = 0; j < rows; j++) {
Generic a = elements[j].derivative(variable[i - 1]);
int k = Math.abs(product[i][j]) - 1;
v.elements[k] = v.elements[k].add(product[i][j] < 0 ? a.negate() : a);
}
}
return v;
}
public Generic conjugate() {
JsclVector v = (JsclVector) newInstance();
for (int i = 0; i < rows; i++) {
v.elements[i] = new Conjugate(elements[i]).selfExpand();
}
return v;
}
public int compareTo(JsclVector vector) {
return ArrayComparator.comparator.compare(elements, vector.elements);
}
public int compareTo(Generic generic) {
if (generic instanceof JsclVector) {
return compareTo((JsclVector) generic);
} else {
return compareTo(valueOf(generic));
}
}
public String toString() {
final StringBuilder result = new StringBuilder();
result.append("[");
for (int i = 0; i < rows; i++) {
result.append(elements[i]).append(i < rows - 1 ? ", " : "");
}
result.append("]");
return result.toString();
}
public String toJava() {
final StringBuilder result = new StringBuilder();
result.append("new Vector(new Numeric[] {");
for (int i = 0; i < rows; i++) {
result.append(elements[i].toJava()).append(i < rows - 1 ? ", " : "");
}
result.append("})");
return result.toString();
}
public void toMathML(MathML element, Object data) {
int exponent = data instanceof Integer ? (Integer) data : 1;
if (exponent == 1) bodyToMathML(element);
else {
MathML e1 = element.element("msup");
bodyToMathML(e1);
MathML e2 = element.element("mn");
e2.appendChild(element.text(String.valueOf(exponent)));
e1.appendChild(e2);
element.appendChild(e1);
}
}
@Nonnull
@Override
public Set<? extends Constant> getConstants() {
final Set<Constant> result = new HashSet<Constant>(elements.length);
for (Generic element : elements) {
result.addAll(element.getConstants());
}
return result;
}
protected void bodyToMathML(MathML e0) {
MathML e1 = e0.element("mfenced");
MathML e2 = e0.element("mtable");
for (int i = 0; i < rows; i++) {
MathML e3 = e0.element("mtr");
MathML e4 = e0.element("mtd");
elements[i].toMathML(e4, null);
e3.appendChild(e4);
e2.appendChild(e3);
}
e1.appendChild(e2);
e0.appendChild(e1);
}
@Nonnull
protected Generic newInstance() {
return newInstance(new Generic[rows]);
}
@Nonnull
protected Generic newInstance(@Nonnull Generic element[]) {
return new JsclVector(element);
}
}

View File

@ -0,0 +1,455 @@
package jscl.math;
import jscl.math.function.Fraction;
import jscl.math.function.Pow;
import jscl.math.polynomial.Monomial;
import jscl.mathml.MathML;
import org.solovyev.common.Converter;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
public class Literal implements Comparable {
private Variable variables[];
private int powers[];
private int degree;
private int size;
Literal() {
}
Literal(int size) {
init(size);
}
public static Literal newInstance() {
return new Literal(0);
}
public static Literal valueOf(Variable variable) {
return valueOf(variable, 1);
}
public static Literal valueOf(Variable variable, int power) {
Literal l = new Literal();
l.init(variable, power);
return l;
}
public static Literal valueOf(Monomial monomial) {
Literal l = new Literal();
l.init(monomial);
return l;
}
public int size() {
return size;
}
@Nonnull
public Variable getVariable(int i) {
return variables[i];
}
public int getPower(int i) {
return powers[i];
}
void init(int size) {
variables = new Variable[size];
powers = new int[size];
this.size = size;
}
void resize(int size) {
if (size < variables.length) {
Variable variable[] = new Variable[size];
int power[] = new int[size];
System.arraycopy(this.variables, 0, variable, 0, size);
System.arraycopy(this.powers, 0, power, 0, size);
this.variables = variable;
this.powers = power;
this.size = size;
}
}
public Literal multiply(@Nonnull Literal that) {
final Literal result = newInstance(size + that.size);
int i = 0;
int thisI = 0;
int thatI = 0;
Variable thisVariable = thisI < this.size ? this.variables[thisI] : null;
Variable thatVariable = thatI < that.size ? that.variables[thatI] : null;
while (thisVariable != null || thatVariable != null) {
int c = thisVariable == null ? 1 : (thatVariable == null ? -1 : thisVariable.compareTo(thatVariable));
if (c < 0) {
int s = powers[thisI];
result.variables[i] = thisVariable;
result.powers[i] = s;
result.degree += s;
i++;
thisI++;
thisVariable = thisI < size ? variables[thisI] : null;
} else if (c > 0) {
int s = that.powers[thatI];
result.variables[i] = thatVariable;
result.powers[i] = s;
result.degree += s;
i++;
thatI++;
thatVariable = thatI < that.size ? that.variables[thatI] : null;
} else {
int s = powers[thisI] + that.powers[thatI];
result.variables[i] = thisVariable;
result.powers[i] = s;
result.degree += s;
i++;
thisI++;
thatI++;
thisVariable = thisI < this.size ? this.variables[thisI] : null;
thatVariable = thatI < that.size ? that.variables[thatI] : null;
}
}
result.resize(i);
return result;
}
public Literal divide(Literal literal) throws ArithmeticException {
Literal l = newInstance(size + literal.size);
int i = 0;
int i1 = 0;
int i2 = 0;
Variable v1 = i1 < size ? variables[i1] : null;
Variable v2 = i2 < literal.size ? literal.variables[i2] : null;
while (v1 != null || v2 != null) {
int c = v1 == null ? 1 : (v2 == null ? -1 : v1.compareTo(v2));
if (c < 0) {
int s = powers[i1];
l.variables[i] = v1;
l.powers[i] = s;
l.degree += s;
i++;
i1++;
v1 = i1 < size ? variables[i1] : null;
} else if (c > 0) {
throw new NotDivisibleException();
} else {
int s = powers[i1] - literal.powers[i2];
if (s < 0) throw new NotDivisibleException();
else if (s == 0) ;
else {
l.variables[i] = v1;
l.powers[i] = s;
l.degree += s;
i++;
}
i1++;
i2++;
v1 = i1 < size ? variables[i1] : null;
v2 = i2 < literal.size ? literal.variables[i2] : null;
}
}
l.resize(i);
return l;
}
@Nonnull
public Literal gcd(@Nonnull Literal that) {
Literal result = newInstance(Math.min(this.size, that.size));
int i = 0;
int thisI = 0;
int thatI = 0;
Variable thisVariable = thisI < this.size ? this.variables[thisI] : null;
Variable thatVariable = thatI < that.size ? that.variables[thatI] : null;
while (thisVariable != null || thatVariable != null) {
int c;
if (thisVariable == null) {
c = 1;
} else if (thatVariable == null) {
c = -1;
} else {
c = thisVariable.compareTo(thatVariable);
}
if (c < 0) {
thisI++;
thisVariable = thisI < this.size ? this.variables[thisI] : null;
} else if (c > 0) {
thatI++;
thatVariable = thatI < that.size ? that.variables[thatI] : null;
} else {
int minPower = Math.min(this.powers[thisI], that.powers[thatI]);
result.variables[i] = thisVariable;
result.powers[i] = minPower;
result.degree += minPower;
i++;
thisI++;
thatI++;
thisVariable = thisI < this.size ? this.variables[thisI] : null;
thatVariable = thatI < that.size ? that.variables[thatI] : null;
}
}
result.resize(i);
return result;
}
public Literal scm(@Nonnull Literal that) {
final Literal result = newInstance(this.size + that.size);
int i = 0;
int thisI = 0;
int thatI = 0;
Variable thisVariable = thisI < this.size ? this.variables[thisI] : null;
Variable thatVariable = thatI < that.size ? that.variables[thatI] : null;
while (thisVariable != null || thatVariable != null) {
int c;
if (thisVariable == null) {
c = 1;
} else if (thatVariable == null) {
c = -1;
} else {
c = thisVariable.compareTo(thatVariable);
}
if (c < 0) {
int thisPower = this.powers[thisI];
result.variables[i] = thisVariable;
result.powers[i] = thisPower;
result.degree += thisPower;
i++;
thisI++;
thisVariable = thisI < size ? variables[thisI] : null;
} else if (c > 0) {
int thatPower = that.powers[thatI];
result.variables[i] = thatVariable;
result.powers[i] = thatPower;
result.degree += thatPower;
i++;
thatI++;
thatVariable = thatI < that.size ? that.variables[thatI] : null;
} else {
int maxPower = Math.max(this.powers[thisI], that.powers[thatI]);
result.variables[i] = thisVariable;
result.powers[i] = maxPower;
result.degree += maxPower;
i++;
thisI++;
thatI++;
thisVariable = thisI < this.size ? this.variables[thisI] : null;
thatVariable = thatI < that.size ? that.variables[thatI] : null;
}
}
result.resize(i);
return result;
}
public Generic[] productValue() throws NotProductException {
Generic a[] = new Generic[size];
for (int i = 0; i < a.length; i++) a[i] = variables[i].expressionValue().pow(powers[i]);
return a;
}
public Power powerValue() throws NotPowerException {
if (size == 0) return new Power(JsclInteger.valueOf(1), 1);
else if (size == 1) {
Variable v = variables[0];
int c = powers[0];
return new Power(v.expressionValue(), c);
} else throw new NotPowerException();
}
public Variable variableValue() throws NotVariableException {
if (size == 0) throw new NotVariableException();
else if (size == 1) {
Variable v = variables[0];
int c = powers[0];
if (c == 1) return v;
else throw new NotVariableException();
} else throw new NotVariableException();
}
public Variable[] variables() {
Variable va[] = new Variable[size];
System.arraycopy(variables, 0, va, 0, size);
return va;
}
public int degree() {
return degree;
}
public int compareTo(@Nonnull Literal that) {
int thisI = this.size;
int thatI = that.size;
Variable thisVariable = thisI == 0 ? null : this.variables[--thisI];
Variable thatVariable = thatI == 0 ? null : that.variables[--thatI];
while (thisVariable != null || thatVariable != null) {
int c;
if (thisVariable == null) {
c = -1;
} else if (thatVariable == null) {
c = 1;
} else {
c = thisVariable.compareTo(thatVariable);
}
if (c < 0) {
return -1;
} else if (c > 0) {
return 1;
} else {
int thisPower = this.powers[thisI];
int thatPower = that.powers[thatI];
if (thisPower < thatPower) {
return -1;
} else if (thisPower > thatPower) {
return 1;
}
thisVariable = thisI == 0 ? null : this.variables[--thisI];
thatVariable = thatI == 0 ? null : that.variables[--thatI];
}
}
return 0;
}
public int compareTo(Object o) {
return compareTo((Literal) o);
}
void init(Variable var, int pow) {
if (pow != 0) {
init(1);
variables[0] = var;
powers[0] = pow;
degree = pow;
} else init(0);
}
void init(Monomial monomial) {
Map map = new TreeMap();
Variable unk[] = monomial.unknown();
for (int i = 0; i < unk.length; i++) {
int c = monomial.element(i);
if (c > 0) map.put(unk[i], c);
}
init(map.size());
Iterator it = map.entrySet().iterator();
for (int i = 0; it.hasNext(); i++) {
Map.Entry e = (Map.Entry) it.next();
Variable v = (Variable) e.getKey();
int c = (Integer) e.getValue();
variables[i] = v;
powers[i] = c;
degree += c;
}
}
Map<Variable, Generic> content(@Nonnull Converter<Variable, Generic> c) {
final Map<Variable, Generic> result = new TreeMap<Variable, Generic>();
for (int i = 0; i < size; i++) {
result.put(variables[i], c.convert(variables[i]));
}
return result;
}
public String toString() {
final StringBuilder result = new StringBuilder();
if (degree == 0) {
result.append("1");
}
// result = var[0] ^ power[0] * var[1] ^ power[1]* ...
for (int i = 0; i < size; i++) {
if (i > 0) {
result.append("*");
}
final Variable var = variables[i];
int power = powers[i];
if (power == 1) {
result.append(var);
} else {
if (var instanceof Fraction || var instanceof Pow) {
result.append("(").append(var).append(")");
} else {
result.append(var);
}
result.append("^").append(power);
}
}
return result.toString();
}
public String toJava() {
StringBuilder buffer = new StringBuilder();
if (degree == 0) buffer.append("JsclDouble.valueOf(1)");
for (int i = 0; i < size; i++) {
if (i > 0) buffer.append(".multiply(");
Variable v = variables[i];
int c = powers[i];
buffer.append(v.toJava());
if (c == 1) ;
else buffer.append(".pow(").append(c).append(")");
if (i > 0) buffer.append(")");
}
return buffer.toString();
}
public void toMathML(MathML element, @Nullable Object data) {
if (degree == 0) {
MathML e1 = element.element("mn");
e1.appendChild(element.text("1"));
element.appendChild(e1);
}
for (int i = 0; i < size; i++) {
Variable v = variables[i];
int c = powers[i];
v.toMathML(element, c);
}
}
@Nonnull
private Literal newInstance(int n) {
return new Literal(n);
}
}

View File

@ -0,0 +1,544 @@
package jscl.math;
import jscl.math.function.Conjugate;
import jscl.math.function.Constant;
import jscl.math.function.Fraction;
import jscl.math.function.trigonometric.Cos;
import jscl.math.function.trigonometric.Sin;
import jscl.mathml.MathML;
import jscl.util.ArrayComparator;
import javax.annotation.Nonnull;
import java.util.HashSet;
import java.util.Set;
public class Matrix extends Generic {
protected final Generic elements[][];
protected final int rows, cols;
public Matrix(Generic elements[][]) {
this.elements = elements;
rows = elements.length;
cols = elements.length > 0 ? elements[0].length : 0;
}
public static boolean isMatrixProduct(@Nonnull Generic a, @Nonnull Generic b) {
return (a instanceof Matrix && b instanceof Matrix) ||
(a instanceof Matrix && b instanceof JsclVector) ||
(a instanceof JsclVector && b instanceof Matrix);
}
public static Matrix identity(int dimension) {
return identity(dimension, dimension);
}
public static Matrix identity(int n, int p) {
Matrix m = new Matrix(new Generic[n][p]);
for (int i = 0; i < n; i++) {
for (int j = 0; j < p; j++) {
if (i == j) {
m.elements[i][j] = JsclInteger.valueOf(1);
} else {
m.elements[i][j] = JsclInteger.valueOf(0);
}
}
}
return m;
}
public static Matrix frame(JsclVector vector[]) {
Matrix m = new Matrix(new Generic[vector.length > 0 ? vector[0].rows : 0][vector.length]);
for (int i = 0; i < m.rows; i++) {
for (int j = 0; j < m.cols; j++) {
m.elements[i][j] = vector[j].elements[i];
}
}
return m;
}
public static Matrix rotation(int dimension, int plane, Generic angle) {
return rotation(dimension, plane, 2, angle);
}
public static Matrix rotation(int dimension, int axis1, int axis2, Generic angle) {
Matrix m = new Matrix(new Generic[dimension][dimension]);
for (int i = 0; i < m.rows; i++) {
for (int j = 0; j < m.cols; j++) {
if (i == axis1 && j == axis1) {
m.elements[i][j] = new Cos(angle).selfExpand();
} else if (i == axis1 && j == axis2) {
m.elements[i][j] = new Sin(angle).selfExpand().negate();
} else if (i == axis2 && j == axis1) {
m.elements[i][j] = new Sin(angle).selfExpand();
} else if (i == axis2 && j == axis2) {
m.elements[i][j] = new Cos(angle).selfExpand();
} else if (i == j) {
m.elements[i][j] = JsclInteger.valueOf(1);
} else {
m.elements[i][j] = JsclInteger.valueOf(0);
}
}
}
return m;
}
@Nonnull
protected static Generic newInstance(Generic element[][]) {
return new Matrix(element);
}
public Generic[][] elements() {
return elements;
}
public Matrix add(Matrix matrix) {
Matrix m = (Matrix) newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m.elements[i][j] = elements[i][j].add(matrix.elements[i][j]);
}
}
return m;
}
@Nonnull
public Generic add(@Nonnull Generic that) {
if (that instanceof Matrix) {
return add((Matrix) that);
} else {
return add(valueOf(that));
}
}
public Matrix subtract(Matrix matrix) {
Matrix m = (Matrix) newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m.elements[i][j] = elements[i][j].subtract(matrix.elements[i][j]);
}
}
return m;
}
@Nonnull
public Generic subtract(@Nonnull Generic that) {
if (that instanceof Matrix) {
return subtract((Matrix) that);
} else {
return subtract(valueOf(that));
}
}
public Matrix multiply(Matrix matrix) {
if (cols != matrix.rows) {
throw new ArithmeticException("Unable to multiply matrix by matrix: number of columns of left matrix doesn't match number of rows of right matrix!");
}
Matrix m = (Matrix) newInstance(new Generic[rows][matrix.cols]);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < matrix.cols; j++) {
m.elements[i][j] = JsclInteger.valueOf(0);
for (int k = 0; k < cols; k++) {
m.elements[i][j] = m.elements[i][j].add(elements[i][k].multiply(matrix.elements[k][j]));
}
}
}
return m;
}
@Nonnull
public Generic multiply(@Nonnull Generic that) {
if (that instanceof Matrix) {
return multiply((Matrix) that);
} else if (that instanceof JsclVector) {
JsclVector v = (JsclVector) ((JsclVector) that).newInstance(new Generic[rows]);
JsclVector v2 = (JsclVector) that;
if (cols != v2.rows) {
throw new ArithmeticException("Unable to multiply matrix by vector: number of matrix columns doesn't match number of vector rows!");
}
for (int i = 0; i < rows; i++) {
v.elements[i] = JsclInteger.valueOf(0);
for (int k = 0; k < cols; k++) {
v.elements[i] = v.elements[i].add(elements[i][k].multiply(v2.elements[k]));
}
}
return v;
} else {
Matrix m = (Matrix) newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m.elements[i][j] = elements[i][j].multiply(that);
}
}
return m;
}
}
@Nonnull
public Generic divide(@Nonnull Generic that) throws NotDivisibleException {
if (that instanceof Matrix) {
return multiply(that.inverse());
} else if (that instanceof JsclVector) {
throw new ArithmeticException("Unable to divide matrix by vector: matrix could not be divided by vector!");
} else {
Matrix m = (Matrix) newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
try {
m.elements[i][j] = elements[i][j].divide(that);
} catch (NotDivisibleException e) {
m.elements[i][j] = new Fraction(elements[i][j], that).selfExpand();
}
}
}
return m;
}
}
public Generic gcd(@Nonnull Generic generic) {
return null;
}
@Nonnull
public Generic gcd() {
return null;
}
public Generic negate() {
Matrix m = (Matrix) newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m.elements[i][j] = elements[i][j].negate();
}
}
return m;
}
public int signum() {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
int c = elements[i][j].signum();
if (c < 0) return -1;
else if (c > 0) return 1;
}
}
return 0;
}
public int degree() {
return 0;
}
public Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException {
Matrix m = (Matrix) newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m.elements[i][j] = elements[i][j].antiDerivative(variable);
}
}
return m;
}
public Generic derivative(@Nonnull Variable variable) {
Matrix m = (Matrix) newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m.elements[i][j] = elements[i][j].derivative(variable);
}
}
return m;
}
public Generic substitute(@Nonnull Variable variable, Generic generic) {
Matrix m = (Matrix) newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m.elements[i][j] = elements[i][j].substitute(variable, generic);
}
}
return m;
}
public Generic expand() {
Matrix m = (Matrix) newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m.elements[i][j] = elements[i][j].expand();
}
}
return m;
}
public Generic factorize() {
Matrix m = (Matrix) newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m.elements[i][j] = elements[i][j].factorize();
}
}
return m;
}
public Generic elementary() {
Matrix m = (Matrix) newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m.elements[i][j] = elements[i][j].elementary();
}
}
return m;
}
public Generic simplify() {
Matrix m = (Matrix) newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m.elements[i][j] = elements[i][j].simplify();
}
}
return m;
}
public Generic numeric() {
return new NumericWrapper(this);
}
public Generic valueOf(Generic generic) {
if (generic instanceof Matrix || generic instanceof JsclVector) {
throw new ArithmeticException("Unable to create matrix: matrix of vectors and matrix of matrices are forbidden");
} else {
Matrix m = (Matrix) identity(rows, cols).multiply(generic);
return newInstance(m.elements);
}
}
public Generic[] sumValue() {
return new Generic[]{this};
}
public Generic[] productValue() throws NotProductException {
return new Generic[]{this};
}
public Power powerValue() throws NotPowerException {
return new Power(this, 1);
}
public Expression expressionValue() throws NotExpressionException {
throw new NotExpressionException();
}
public JsclInteger integerValue() throws NotIntegerException {
throw new NotIntegerException();
}
@Override
public boolean isInteger() {
return false;
}
public Variable variableValue() throws NotVariableException {
throw new NotVariableException();
}
public Variable[] variables() {
return null;
}
public boolean isPolynomial(@Nonnull Variable variable) {
return false;
}
public boolean isConstant(@Nonnull Variable variable) {
return false;
}
public Generic[] vectors() {
JsclVector v[] = new JsclVector[rows];
for (int i = 0; i < rows; i++) {
v[i] = new JsclVector(new Generic[cols]);
for (int j = 0; j < cols; j++) {
v[i].elements[j] = elements[i][j];
}
}
return v;
}
public Generic tensorProduct(Matrix matrix) {
Matrix m = (Matrix) newInstance(new Generic[rows * matrix.rows][cols * matrix.cols]);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
for (int k = 0; k < matrix.rows; k++) {
for (int l = 0; l < matrix.cols; l++) {
m.elements[i * matrix.rows + k][j * matrix.cols + l] = elements[i][j].multiply(matrix.elements[k][l]);
}
}
}
}
return m;
}
public Matrix transpose() {
Matrix m = (Matrix) newInstance(new Generic[cols][rows]);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m.elements[j][i] = elements[i][j];
}
}
return m;
}
public Generic trace() {
Generic s = JsclInteger.valueOf(0);
for (int i = 0; i < rows; i++) {
s = s.add(elements[i][i]);
}
return s;
}
public Generic inverse() {
Matrix m = (Matrix) newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < rows; j++) {
m.elements[i][j] = inverseElement(i, j);
}
}
return m.transpose().divide(determinant());
}
Generic inverseElement(int k, int l) {
Matrix m = (Matrix) newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < rows; j++) {
m.elements[i][j] = i == k ? JsclInteger.valueOf(j == l ? 1 : 0) : elements[i][j];
}
}
return m.determinant();
}
public Generic determinant() {
if (rows > 1) {
Generic a = JsclInteger.valueOf(0);
for (int i = 0; i < rows; i++) {
if (elements[i][0].signum() == 0) ;
else {
Matrix m = (Matrix) newInstance(new Generic[rows - 1][rows - 1]);
for (int j = 0; j < rows - 1; j++) {
for (int k = 0; k < rows - 1; k++) m.elements[j][k] = elements[j < i ? j : j + 1][k + 1];
}
if (i % 2 == 0) a = a.add(elements[i][0].multiply(m.determinant()));
else a = a.subtract(elements[i][0].multiply(m.determinant()));
}
}
return a;
} else if (rows > 0) return elements[0][0];
else return JsclInteger.valueOf(0);
}
public Generic conjugate() {
Matrix m = (Matrix) newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m.elements[i][j] = new Conjugate(elements[i][j]).selfExpand();
}
}
return m;
}
public int compareTo(Matrix matrix) {
return ArrayComparator.comparator.compare(vectors(), matrix.vectors());
}
public int compareTo(Generic generic) {
if (generic instanceof Matrix) {
return compareTo((Matrix) generic);
} else {
return compareTo(valueOf(generic));
}
}
public String toString() {
final StringBuilder result = new StringBuilder();
result.append("[");
for (int i = 0; i < rows; i++) {
result.append("[");
for (int j = 0; j < cols; j++) {
result.append(elements[i][j]).append(j < cols - 1 ? ", " : "");
}
result.append("]").append(i < rows - 1 ? ",\n" : "");
}
result.append("]");
return result.toString();
}
public String toJava() {
final StringBuilder result = new StringBuilder();
result.append("new Matrix(new Numeric[][] {");
for (int i = 0; i < rows; i++) {
result.append("{");
for (int j = 0; j < cols; j++) {
result.append(elements[i][j].toJava()).append(j < cols - 1 ? ", " : "");
}
result.append("}").append(i < rows - 1 ? ", " : "");
}
result.append("})");
return result.toString();
}
public void toMathML(MathML element, Object data) {
int exponent = data instanceof Integer ? (Integer) data : 1;
if (exponent == 1) bodyToMathML(element);
else {
MathML e1 = element.element("msup");
bodyToMathML(e1);
MathML e2 = element.element("mn");
e2.appendChild(element.text(String.valueOf(exponent)));
e1.appendChild(e2);
element.appendChild(e1);
}
}
@Nonnull
@Override
public Set<? extends Constant> getConstants() {
final Set<Constant> result = new HashSet<Constant>();
for (Generic[] element : elements) {
for (Generic generic : element) {
result.addAll(generic.getConstants());
}
}
return result;
}
protected void bodyToMathML(MathML e0) {
MathML e1 = e0.element("mfenced");
MathML e2 = e0.element("mtable");
for (int i = 0; i < rows; i++) {
MathML e3 = e0.element("mtr");
for (int j = 0; j < cols; j++) {
MathML e4 = e0.element("mtd");
elements[i][j].toMathML(e4, null);
e3.appendChild(e4);
}
e2.appendChild(e3);
}
e1.appendChild(e2);
e0.appendChild(e1);
}
@Nonnull
protected Generic newInstance() {
return newInstance(new Generic[rows][cols]);
}
}

View File

@ -0,0 +1,14 @@
package jscl.math;
import javax.annotation.Nonnull;
public class MatrixVariable extends GenericVariable {
public MatrixVariable(Generic generic) {
super(generic);
}
@Nonnull
public Variable newInstance() {
return new MatrixVariable(null);
}
}

View File

@ -0,0 +1,210 @@
package jscl.math;
import jscl.math.function.Constant;
import jscl.mathml.MathML;
import javax.annotation.Nonnull;
import java.math.BigInteger;
import java.util.Collections;
import java.util.Set;
public class ModularInteger extends Generic implements Field {
public static final ModularInteger booleanFactory = new ModularInteger(0, 2);
final int modulo;
final int content;
public ModularInteger(long content, int modulo) {
this.modulo = modulo;
this.content = (int) (content % modulo);
}
public static ModularInteger factory(int modulo) {
return new ModularInteger(0, modulo);
}
public int content() {
return content;
}
public int modulo() {
return modulo;
}
public ModularInteger add(ModularInteger integer) {
return newinstance((long) content + integer.content);
}
@Nonnull
public Generic add(@Nonnull Generic that) {
return add((ModularInteger) that);
}
public ModularInteger subtract(ModularInteger integer) {
return newinstance((long) content + (modulo - integer.content));
}
@Nonnull
public Generic subtract(@Nonnull Generic that) {
return subtract((ModularInteger) that);
}
public ModularInteger multiply(ModularInteger integer) {
return newinstance((long) content * integer.content);
}
@Nonnull
public Generic multiply(@Nonnull Generic that) {
return multiply((ModularInteger) that);
}
@Nonnull
public Generic divide(@Nonnull Generic that) throws NotDivisibleException {
return multiply(that.inverse());
}
public Generic inverse() {
return newinstance(BigInteger.valueOf(content).modInverse(BigInteger.valueOf(modulo)).intValue());
}
public Generic gcd(@Nonnull Generic generic) {
throw new UnsupportedOperationException();
}
@Nonnull
public Generic gcd() {
throw new UnsupportedOperationException();
}
public Generic pow(int exponent) {
throw new UnsupportedOperationException();
}
public Generic negate() {
return newinstance(modulo - content);
}
public int signum() {
return content > 0 ? 1 : 0;
}
public int degree() {
return 0;
}
public Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException {
throw new UnsupportedOperationException();
}
public Generic derivative(@Nonnull Variable variable) {
throw new UnsupportedOperationException();
}
public Generic substitute(@Nonnull Variable variable, Generic generic) {
throw new UnsupportedOperationException();
}
public Generic expand() {
throw new UnsupportedOperationException();
}
public Generic factorize() {
throw new UnsupportedOperationException();
}
public Generic elementary() {
throw new UnsupportedOperationException();
}
public Generic simplify() {
throw new UnsupportedOperationException();
}
public Generic numeric() {
throw new UnsupportedOperationException();
}
public Generic valueOf(Generic generic) {
if (generic instanceof ModularInteger) {
return newinstance(((ModularInteger) generic).content);
} else {
return newinstance(((JsclInteger) generic).content().mod(BigInteger.valueOf(modulo)).intValue());
}
}
public Generic[] sumValue() {
throw new UnsupportedOperationException();
}
public Generic[] productValue() throws NotProductException {
throw new UnsupportedOperationException();
}
public Power powerValue() throws NotPowerException {
throw new UnsupportedOperationException();
}
public Expression expressionValue() throws NotExpressionException {
return Expression.valueOf(integerValue());
}
public JsclInteger integerValue() throws NotIntegerException {
return JsclInteger.valueOf(content);
}
@Override
public boolean isInteger() {
return true;
}
public Variable variableValue() throws NotVariableException {
throw new UnsupportedOperationException();
}
public Variable[] variables() {
throw new UnsupportedOperationException();
}
public boolean isPolynomial(@Nonnull Variable variable) {
throw new UnsupportedOperationException();
}
public boolean isConstant(@Nonnull Variable variable) {
throw new UnsupportedOperationException();
}
public int compareTo(ModularInteger integer) {
return content < integer.content ? -1 : content > integer.content ? 1 : 0;
}
public int compareTo(Generic generic) {
if (generic instanceof ModularInteger) {
return compareTo((ModularInteger) generic);
} else if (generic instanceof JsclInteger) {
return compareTo(valueOf(generic));
} else {
throw new UnsupportedOperationException();
}
}
public String toString() {
return "" + content;
}
public String toJava() {
throw new UnsupportedOperationException();
}
public void toMathML(MathML element, Object data) {
throw new UnsupportedOperationException();
}
@Nonnull
@Override
public Set<? extends Constant> getConstants() {
return Collections.emptySet();
}
protected ModularInteger newinstance(long content) {
return new ModularInteger(content, modulo);
}
}

View File

@ -0,0 +1,11 @@
package jscl.math;
public class NotDivisibleException extends ArithmeticException {
public NotDivisibleException() {
}
public NotDivisibleException(String s) {
super(s);
}
}

View File

@ -0,0 +1,10 @@
package jscl.math;
public class NotExpressionException extends ArithmeticException {
public NotExpressionException() {
}
public NotExpressionException(String s) {
super(s);
}
}

View File

@ -0,0 +1,11 @@
package jscl.math;
public class NotIntegerException extends ArithmeticException {
public NotIntegerException() {
this("Not integer!");
}
public NotIntegerException(String s) {
super(s);
}
}

View File

@ -0,0 +1,25 @@
package jscl.math;
import jscl.AbstractJsclArithmeticException;
import jscl.text.msg.Messages;
import javax.annotation.Nonnull;
public class NotIntegrableException extends AbstractJsclArithmeticException {
public NotIntegrableException(@Nonnull String messageCode, Object... parameters) {
super(messageCode, parameters);
}
public NotIntegrableException(@Nonnull Expression e) {
this(Messages.msg_21, e.toString());
}
public NotIntegrableException(@Nonnull Variable v) {
this(Messages.msg_21, v.getName());
}
public NotIntegrableException() {
this(Messages.msg_22);
}
}

View File

@ -0,0 +1,10 @@
package jscl.math;
public class NotPowerException extends ArithmeticException {
public NotPowerException() {
}
public NotPowerException(String s) {
super(s);
}
}

View File

@ -0,0 +1,10 @@
package jscl.math;
public class NotProductException extends ArithmeticException {
public NotProductException() {
}
public NotProductException(String s) {
super(s);
}
}

View File

@ -0,0 +1,10 @@
package jscl.math;
public class NotVariableException extends ArithmeticException {
public NotVariableException() {
}
public NotVariableException(String s) {
super(s);
}
}

View File

@ -0,0 +1,445 @@
package jscl.math;
import jscl.JsclMathEngine;
import jscl.math.function.Constant;
import jscl.math.function.Constants;
import jscl.math.function.IConstant;
import jscl.math.numeric.*;
import jscl.mathml.MathML;
import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.Set;
public final class NumericWrapper extends Generic implements INumeric<NumericWrapper> {
@Nonnull
private final Numeric content;
public NumericWrapper(@Nonnull JsclInteger integer) {
content = Real.valueOf(integer.content().doubleValue());
}
public NumericWrapper(@Nonnull Rational rational) {
content = Real.valueOf(rational.numerator().doubleValue() / rational.denominator().doubleValue());
}
public NumericWrapper(@Nonnull JsclVector vector) {
final Numeric elements[] = new Numeric[vector.rows];
for (int i = 0; i < vector.rows; i++) {
elements[i] = ((NumericWrapper) vector.elements[i].numeric()).content();
}
content = new Vector(elements);
}
public NumericWrapper(@Nonnull Matrix matrix) {
final Numeric elements[][] = new Numeric[matrix.rows][matrix.cols];
for (int i = 0; i < matrix.rows; i++) {
for (int j = 0; j < matrix.cols; j++) {
elements[i][j] = ((NumericWrapper) matrix.elements[i][j].numeric()).content();
}
}
content = new jscl.math.numeric.Matrix(elements);
}
public NumericWrapper(@Nonnull Constant constant) {
final IConstant constantFromRegistry = JsclMathEngine.getInstance().getConstantsRegistry().get(constant.getName());
if (constantFromRegistry != null) {
if (constantFromRegistry.getName().equals(Constants.I.getName())) {
content = Complex.I;
} else {
if (constantFromRegistry.getValue() != null) {
final Double value = constantFromRegistry.getDoubleValue();
if (value == null) {
throw new ArithmeticException("Constant " + constant.getName() + " has invalid definition: " + constantFromRegistry.getValue());
} else {
content = Real.valueOf(value);
}
} else {
throw new ArithmeticException("Could not create numeric wrapper: constant in registry doesn't have specified value: " + constant.getName());
}
}
} else {
throw new ArithmeticException("Could not create numeric wrapper: constant is not registered in constants registry: " + constant.getName());
}
}
public NumericWrapper(@Nonnull Numeric numeric) {
content = numeric;
}
public static Generic root(int subscript, Generic parameter[]) {
Numeric param[] = new Numeric[parameter.length];
for (int i = 0; i < param.length; i++) param[i] = ((NumericWrapper) parameter[i]).content;
return new NumericWrapper(Numeric.root(subscript, param));
}
public Numeric content() {
return content;
}
public NumericWrapper add(NumericWrapper wrapper) {
return new NumericWrapper(content.add(wrapper.content));
}
@Nonnull
public Generic add(@Nonnull Generic that) {
if (that instanceof Expression) {
return that.add(this);
} else if (that instanceof NumericWrapper) {
return add((NumericWrapper) that);
} else {
return add(valueOf(that));
}
}
public NumericWrapper subtract(NumericWrapper wrapper) {
return new NumericWrapper(content.subtract(wrapper.content));
}
@Nonnull
public Generic subtract(@Nonnull Generic that) {
if (that instanceof Expression) {
return that.add(this);
} else if (that instanceof NumericWrapper) {
return subtract((NumericWrapper) that);
} else {
return subtract(valueOf(that));
}
}
public NumericWrapper multiply(NumericWrapper wrapper) {
return new NumericWrapper(content.multiply(wrapper.content));
}
@Nonnull
public Generic multiply(@Nonnull Generic that) {
if (that instanceof Expression) {
return that.add(this);
} else if (that instanceof NumericWrapper) {
return multiply((NumericWrapper) that);
} else {
return multiply(valueOf(that));
}
}
public NumericWrapper divide(NumericWrapper wrapper) throws ArithmeticException {
return new NumericWrapper(content.divide(wrapper.content));
}
@Nonnull
public Generic divide(@Nonnull Generic that) throws NotDivisibleException {
if (that instanceof Expression) {
return that.add(this);
} else if (that instanceof NumericWrapper) {
return divide((NumericWrapper) that);
} else {
return divide(valueOf(that));
}
}
public Generic gcd(@Nonnull Generic generic) {
return null;
}
@Nonnull
public Generic gcd() {
return null;
}
@Nonnull
public NumericWrapper abs() {
return new NumericWrapper(content.abs());
}
@Nonnull
public NumericWrapper negate() {
return new NumericWrapper(content.negate());
}
public int signum() {
return content.signum();
}
public int degree() {
return 0;
}
public Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException {
return null;
}
public Generic derivative(@Nonnull Variable variable) {
return null;
}
public Generic substitute(@Nonnull Variable variable, Generic generic) {
return null;
}
public Generic expand() {
return null;
}
public Generic factorize() {
return null;
}
public Generic elementary() {
return null;
}
public Generic simplify() {
return null;
}
public Generic numeric() {
return this;
}
public NumericWrapper valueOf(NumericWrapper wrapper) {
return new NumericWrapper(content.valueOf(wrapper.content));
}
public Generic valueOf(@Nonnull Generic generic) {
if (generic instanceof NumericWrapper) {
return valueOf((NumericWrapper) generic);
} else if (generic instanceof JsclInteger) {
return new NumericWrapper((JsclInteger) generic);
} else {
throw new ArithmeticException("Could not create numeric wrapper for class: " + generic.getClass());
}
}
public Generic[] sumValue() {
return null;
}
public Generic[] productValue() throws NotProductException {
return null;
}
public Power powerValue() throws NotPowerException {
return null;
}
public Expression expressionValue() throws NotExpressionException {
throw new NotExpressionException();
}
public JsclInteger integerValue() throws NotIntegerException {
if (content instanceof Real) {
double doubleValue = ((Real) content).doubleValue();
if (Math.floor(doubleValue) == doubleValue) {
return JsclInteger.valueOf((int) doubleValue);
} else {
throw new NotIntegerException();
}
} else {
throw new NotIntegerException();
}
}
@Override
public boolean isInteger() {
if (content instanceof Real) {
double value = ((Real) content).doubleValue();
return Math.floor(value) == value;
}
return false;
}
public Variable variableValue() throws NotVariableException {
throw new NotVariableException();
}
public Variable[] variables() {
return new Variable[0];
}
public boolean isPolynomial(@Nonnull Variable variable) {
return true;
}
public boolean isConstant(@Nonnull Variable variable) {
return true;
}
@Nonnull
public NumericWrapper sgn() {
return new NumericWrapper(content.sgn());
}
@Nonnull
public NumericWrapper ln() {
return new NumericWrapper(content.ln());
}
@Nonnull
public NumericWrapper lg() {
return new NumericWrapper(content.lg());
}
@Nonnull
public NumericWrapper exp() {
return new NumericWrapper(content.exp());
}
@Nonnull
public NumericWrapper inverse() {
return new NumericWrapper(content.inverse());
}
@Nonnull
public NumericWrapper pow(int exponent) {
return new NumericWrapper(content.pow(exponent));
}
public Generic pow(Generic generic) {
return new NumericWrapper(content.pow(((NumericWrapper) generic).content));
}
@Nonnull
public NumericWrapper sqrt() {
return new NumericWrapper(content.sqrt());
}
@Nonnull
public NumericWrapper nThRoot(int n) {
return new NumericWrapper(content.nThRoot(n));
}
public Generic conjugate() {
return new NumericWrapper(content.conjugate());
}
@Nonnull
public NumericWrapper acos() {
return new NumericWrapper(content.acos());
}
@Nonnull
public NumericWrapper asin() {
return new NumericWrapper(content.asin());
}
@Nonnull
public NumericWrapper atan() {
return new NumericWrapper(content.atan());
}
@Nonnull
public NumericWrapper acot() {
return new NumericWrapper(content.acot());
}
@Nonnull
public NumericWrapper cos() {
return new NumericWrapper(content.cos());
}
@Nonnull
public NumericWrapper sin() {
return new NumericWrapper(content.sin());
}
@Nonnull
public NumericWrapper tan() {
return new NumericWrapper(content.tan());
}
@Nonnull
public NumericWrapper cot() {
return new NumericWrapper(content.cot());
}
@Nonnull
public NumericWrapper acosh() {
return new NumericWrapper(content.acosh());
}
@Nonnull
public NumericWrapper asinh() {
return new NumericWrapper(content.asinh());
}
@Nonnull
public NumericWrapper atanh() {
return new NumericWrapper(content.atanh());
}
@Nonnull
public NumericWrapper acoth() {
return new NumericWrapper(content.acoth());
}
@Nonnull
public NumericWrapper cosh() {
return new NumericWrapper(content.cosh());
}
@Nonnull
public NumericWrapper sinh() {
return new NumericWrapper(content.sinh());
}
@Nonnull
public NumericWrapper tanh() {
return new NumericWrapper(content.tanh());
}
@Nonnull
public NumericWrapper coth() {
return new NumericWrapper(content.coth());
}
public int compareTo(NumericWrapper wrapper) {
return content.compareTo(wrapper.content);
}
public int compareTo(Generic generic) {
if (generic instanceof NumericWrapper) {
return compareTo((NumericWrapper) generic);
} else {
return compareTo(valueOf(generic));
}
}
public String toString() {
return content.toString();
}
public String toJava() {
return "JsclDouble.valueOf(" + new Double(((Real) content).doubleValue()) + ")";
}
public void toMathML(MathML element, Object data) {
int exponent = data instanceof Integer ? (Integer) data : 1;
if (exponent == 1) bodyToMathML(element);
else {
MathML e1 = element.element("msup");
bodyToMathML(e1);
MathML e2 = element.element("mn");
e2.appendChild(element.text(String.valueOf(exponent)));
e1.appendChild(e2);
element.appendChild(e1);
}
}
@Nonnull
@Override
public Set<? extends Constant> getConstants() {
return Collections.emptySet();
}
void bodyToMathML(MathML element) {
MathML e1 = element.element("mn");
e1.appendChild(element.text(String.valueOf(new Double(((Real) content).doubleValue()))));
element.appendChild(e1);
}
}

View File

@ -0,0 +1,27 @@
package jscl.math;
public class Power {
final Generic value;
final int exponent;
public Power(Generic value, int exponent) {
this.value = value;
this.exponent = exponent;
}
public Generic value() {
return value(false);
}
public Generic value(boolean content) {
return content ? GenericVariable.content(value) : value;
}
public int exponent() {
return exponent;
}
public String toString() {
return "(" + value + ", " + exponent + ")";
}
}

View File

@ -0,0 +1,311 @@
package jscl.math;
import jscl.math.function.Constant;
import jscl.math.function.Fraction;
import jscl.math.function.Inverse;
import jscl.mathml.MathML;
import javax.annotation.Nonnull;
import java.math.BigInteger;
import java.util.Collections;
import java.util.Set;
public final class Rational extends Generic implements Field {
public static final Rational factory = new Rational(BigInteger.valueOf(0), BigInteger.valueOf(1));
final BigInteger numerator;
final BigInteger denominator;
public Rational(BigInteger numerator, BigInteger denominator) {
this.numerator = numerator;
this.denominator = denominator;
}
static BigInteger scm(BigInteger b1, BigInteger b2) {
return b1.multiply(b2).divide(b1.gcd(b2));
}
public BigInteger numerator() {
return numerator;
}
public BigInteger denominator() {
return denominator;
}
public Rational add(Rational rational) {
BigInteger gcd = denominator.gcd(rational.denominator);
BigInteger c = denominator.divide(gcd);
BigInteger c2 = rational.denominator.divide(gcd);
return new Rational(numerator.multiply(c2).add(rational.numerator.multiply(c)), denominator.multiply(c2)).reduce();
}
Rational reduce() {
BigInteger gcd = numerator.gcd(denominator);
if (gcd.signum() != denominator.signum()) gcd = gcd.negate();
return gcd.signum() == 0 ? this : new Rational(numerator.divide(gcd), denominator.divide(gcd));
}
@Nonnull
public Generic add(@Nonnull Generic that) {
if (that instanceof Rational) {
return add((Rational) that);
} else if (that instanceof JsclInteger) {
return add(valueOf(that));
} else {
return that.valueOf(this).add(that);
}
}
public Rational multiply(Rational rational) {
BigInteger gcd = numerator.gcd(rational.denominator);
BigInteger gcd2 = denominator.gcd(rational.numerator);
return new Rational(numerator.divide(gcd).multiply(rational.numerator.divide(gcd2)), denominator.divide(gcd2).multiply(rational.denominator.divide(gcd)));
}
@Nonnull
public Generic multiply(@Nonnull Generic that) {
if (that instanceof Rational) {
return multiply((Rational) that);
} else if (that instanceof JsclInteger) {
return multiply(valueOf(that));
} else {
return that.multiply(this);
}
}
@Nonnull
public Generic divide(@Nonnull Generic that) throws NotDivisibleException {
if (that instanceof Rational) {
return multiply(that.inverse());
} else if (that instanceof JsclInteger) {
return divide(valueOf(that));
} else {
return that.valueOf(this).divide(that);
}
}
public Generic inverse() {
if (signum() < 0) return new Rational(denominator.negate(), numerator.negate());
else return new Rational(denominator, numerator);
}
public Rational gcd(Rational rational) {
return new Rational(numerator.gcd(rational.numerator), scm(denominator, rational.denominator));
}
public Generic gcd(@Nonnull Generic generic) {
if (generic instanceof Rational) {
return gcd((Rational) generic);
} else if (generic instanceof JsclInteger) {
return gcd(valueOf(generic));
} else {
return generic.valueOf(this).gcd(generic);
}
}
@Nonnull
public Generic gcd() {
return null;
}
public Generic pow(int exponent) {
return null;
}
public Generic negate() {
return new Rational(numerator.negate(), denominator);
}
public int signum() {
return numerator.signum();
}
public int degree() {
return 0;
}
public Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException {
return multiply(variable.expressionValue());
}
public Generic derivative(@Nonnull Variable variable) {
return JsclInteger.valueOf(0);
}
public Generic substitute(@Nonnull Variable variable, Generic generic) {
return this;
}
public Generic expand() {
return this;
}
public Generic factorize() {
return expressionValue().factorize();
}
public Generic elementary() {
return this;
}
public Generic simplify() {
return reduce();
}
public Generic numeric() {
return new NumericWrapper(this);
}
public Generic valueOf(Generic generic) {
if (generic instanceof Rational) {
Rational r = (Rational) generic;
return new Rational(r.numerator, r.denominator);
} else if (generic instanceof Expression) {
boolean sign = generic.signum() < 0;
Generic g[] = ((Fraction) (sign ? generic.negate() : generic).variableValue()).getParameters();
JsclInteger numerator = (JsclInteger) (sign ? g[0].negate() : g[0]);
JsclInteger denominator = (JsclInteger) g[1];
return new Rational(numerator.content(), denominator.content());
} else {
JsclInteger en = (JsclInteger) generic;
return new Rational(en.content(), BigInteger.valueOf(1));
}
}
public Generic[] sumValue() {
try {
if (integerValue().signum() == 0) return new Generic[0];
else return new Generic[]{this};
} catch (NotIntegerException e) {
return new Generic[]{this};
}
}
public Generic[] productValue() throws NotProductException {
try {
if (integerValue().compareTo(JsclInteger.valueOf(1)) == 0) return new Generic[0];
else return new Generic[]{this};
} catch (NotIntegerException e) {
return new Generic[]{this};
}
}
public Power powerValue() throws NotPowerException {
return new Power(this, 1);
}
public Expression expressionValue() throws NotExpressionException {
return Expression.valueOf(this);
}
public JsclInteger integerValue() throws NotIntegerException {
if (denominator.compareTo(BigInteger.ONE) == 0) {
return new JsclInteger(numerator);
} else {
throw new NotIntegerException();
}
}
@Override
public boolean isInteger() {
try {
integerValue();
return true;
} catch (NotIntegerException e) {
return false;
}
}
public Variable variableValue() throws NotVariableException {
try {
integerValue();
throw new NotVariableException();
} catch (NotIntegerException e) {
if (numerator.compareTo(BigInteger.valueOf(1)) == 0) return new Inverse(new JsclInteger(denominator));
else return new Fraction(new JsclInteger(numerator), new JsclInteger(denominator));
}
}
public Variable[] variables() {
return new Variable[0];
}
public boolean isPolynomial(@Nonnull Variable variable) {
return true;
}
public boolean isConstant(@Nonnull Variable variable) {
return true;
}
public int compareTo(Rational rational) {
int c = denominator.compareTo(rational.denominator);
if (c < 0) return -1;
else if (c > 0) return 1;
else return numerator.compareTo(rational.numerator);
}
public int compareTo(Generic generic) {
if (generic instanceof Rational) {
return compareTo((Rational) generic);
} else if (generic instanceof JsclInteger) {
return compareTo(valueOf(generic));
} else {
return generic.valueOf(this).compareTo(generic);
}
}
public String toString() {
final StringBuilder result = new StringBuilder();
try {
result.append(integerValue());
} catch (NotIntegerException e) {
result.append(numerator);
result.append("/");
result.append(denominator);
}
return result.toString();
}
public String toJava() {
return "JsclDouble.valueOf(" + numerator + "/" + denominator + ")";
}
public void toMathML(MathML element, Object data) {
int exponent = data instanceof Integer ? (Integer) data : 1;
if (exponent == 1) bodyToMathML(element);
else {
MathML e1 = element.element("msup");
bodyToMathML(e1);
MathML e2 = element.element("mn");
e2.appendChild(element.text(String.valueOf(exponent)));
e1.appendChild(e2);
element.appendChild(e1);
}
}
@Nonnull
@Override
public Set<? extends Constant> getConstants() {
return Collections.emptySet();
}
void bodyToMathML(MathML element) {
try {
MathML e1 = element.element("mn");
e1.appendChild(element.text(String.valueOf(integerValue())));
element.appendChild(e1);
} catch (NotIntegerException e) {
MathML e1 = element.element("mfrac");
MathML e2 = element.element("mn");
e2.appendChild(element.text(String.valueOf(numerator)));
e1.appendChild(e2);
e2 = element.element("mn");
e2.appendChild(element.text(String.valueOf(denominator)));
e1.appendChild(e2);
element.appendChild(e1);
}
}
}

View File

@ -0,0 +1,266 @@
package jscl.math;
import jscl.math.function.*;
import jscl.math.polynomial.Basis;
import jscl.math.polynomial.Monomial;
import jscl.math.polynomial.Polynomial;
import jscl.math.polynomial.UnivariatePolynomial;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public final class Simplification {
private final Map<Variable, Generic> cache = new TreeMap<Variable, Generic>();
private final List<Constraint> constraints = new ArrayList<Constraint>();
Generic result;
boolean linear;
private Simplification() {
}
public static Generic compute(@Nonnull Generic generic) {
final Simplification s = new Simplification();
s.computeValue(generic);
return s.getValue();
}
void computeValue(Generic generic) {
Debug.println("simplification");
Debug.increment();
final Variable t = new TechnicalVariable("t");
linear = false;
process(new Constraint(t, t.expressionValue().subtract(generic), false));
UnivariatePolynomial p = polynomial(t);
switch (p.degree()) {
case 0:
result = generic;
break;
case 1:
result = new Root(p, 0).selfSimplify();
break;
// case 2:
// int n=branch(generic,p);
// if(n<p.degree()) linear(new Root(p,n).expressionValue());
// else linear(generic);
// break;
default:
linear(generic);
}
Debug.decrement();
}
void linear(Generic generic) {
Variable t = new TechnicalVariable("t");
linear = true;
constraints.clear();
process(new Constraint(t, t.expressionValue().subtract(generic), false));
UnivariatePolynomial p = polynomial(t);
switch (p.degree()) {
case 0:
result = generic;
break;
default:
result = new Root(p, 0).selfSimplify();
}
}
int branch(Generic generic, UnivariatePolynomial polynomial) {
int n = polynomial.degree();
Variable t = new TechnicalVariable("t");
linear = true;
for (int i = 0; i < n; i++) {
constraints.clear();
process(new Constraint(t, t.expressionValue().subtract(generic.subtract(new Root(polynomial, i).expressionValue())), false));
Generic a = polynomial(t).solve();
if (a != null && a.signum() == 0) {
return i;
}
}
return n;
}
UnivariatePolynomial polynomial(Variable t) {
Polynomial fact = Polynomial.factory(t);
int n = constraints.size();
Generic a[] = new Generic[n];
Variable unk[] = new Variable[n];
if (linear) {
int j = 0;
for (Constraint constraint : constraints) {
if (constraint.reduce) {
a[j] = constraint.generic;
unk[j] = constraint.unknown;
j++;
}
}
int k = 0;
for (Constraint c : constraints) {
if (!c.reduce) {
a[j] = c.generic;
unk[j] = c.unknown;
j++;
k++;
}
}
a = solve(a, unk, k);
for (Generic anA : a) {
UnivariatePolynomial p = (UnivariatePolynomial) fact.valueOf(anA);
if (p.degree() == 1) return p;
}
return null;
} else {
for (int i = 0; i < n; i++) {
Constraint c = constraints.get(i);
a[i] = c.generic;
unk[i] = c.unknown;
}
a = solve(a, unk, n);
return (UnivariatePolynomial) fact.valueOf(a[0]);
}
}
Generic[] solve(Generic generic[], Variable unknown[], int n) {
Variable unk[] = Basis.augmentUnknown(unknown, generic);
return Basis.compute(generic, unk, Monomial.kthElimination(n)).elements();
}
void process(@Nonnull Constraint c) {
constraints.add(c);
int n1 = 0;
int n2 = 0;
do {
n1 = n2;
n2 = constraints.size();
for (int i = n1; i < n2; i++) {
subProcess(constraints.get(i));
}
} while (n1 < n2);
}
void subProcess(@Nonnull Constraint c) {
for (Variable v : c.generic.variables()) {
if (constraints.contains(new Constraint(v))) {
continue;
}
Constraint result = null;
if (v instanceof Fraction) {
final Generic parameters[] = ((Fraction) v).getParameters();
result = new Constraint(v, v.expressionValue().multiply(parameters[1]).subtract(parameters[0]), false);
} else if (v instanceof Sqrt) {
if (linear) {
result = linearConstraint(v);
}
if (result == null) {
final Generic parameters[] = ((Sqrt) v).getParameters();
result = new Constraint(v, v.expressionValue().pow(2).subtract(parameters[0]), true);
}
} else if (v instanceof Cubic) {
if (linear) {
result = linearConstraint(v);
}
if (result == null) {
final Generic parameters[] = ((Cubic) v).getParameters();
result = new Constraint(v, v.expressionValue().pow(3).subtract(parameters[0]), true);
}
} else if (v instanceof Pow) {
try {
Root r = ((Pow) v).rootValue();
int d = r.degree();
if (linear) {
result = linearConstraint(v);
}
if (result == null) {
final Generic parameters[] = r.getParameters();
result = new Constraint(v, v.expressionValue().pow(d).subtract(parameters[0].negate()), d > 1);
}
} catch (NotRootException e) {
result = linearConstraint(v);
}
} else if (v instanceof Root) {
try {
Root r = (Root) v;
int d = r.degree();
int n = r.subscript().integerValue().intValue();
if (linear) {
result = linearConstraint(v);
}
if (result == null) {
final Generic parameters[] = r.getParameters();
result = new Constraint(v, Root.sigma(parameters, d - n).multiply(JsclInteger.valueOf(-1).pow(d - n)).multiply(parameters[d]).subtract(parameters[n]), d > 1);
}
} catch (NotIntegerException e) {
result = linearConstraint(v);
}
} else {
result = linearConstraint(v);
}
if (result != null) {
constraints.add(result);
}
}
}
@Nullable
private Constraint linearConstraint(@Nonnull Variable v) {
Generic s = cache.get(v);
if (s == null) {
s = v.simplify();
cache.put(v, s);
}
Generic a = v.expressionValue().subtract(s);
if (a.signum() != 0) {
return new Constraint(v, a, false);
} else {
return null;
}
}
Generic getValue() {
return result;
}
}
class Constraint {
Variable unknown;
Generic generic;
boolean reduce;
Constraint(Variable unknown, Generic generic, boolean reduce) {
this.unknown = unknown;
this.generic = generic;
this.reduce = reduce;
}
Constraint(Variable unknown) {
this(unknown, null, false);
}
public boolean equals(Object obj) {
return unknown.compareTo(((Constraint) obj).unknown) == 0;
}
}

View File

@ -0,0 +1,111 @@
package jscl.math;
import jscl.math.function.Constant;
import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.Set;
public class TechnicalVariable extends Variable {
public int subscript[];
public TechnicalVariable(String name) {
this(name, new int[0]);
}
public TechnicalVariable(String name, int subscript[]) {
super(name);
this.subscript = subscript;
}
public Generic antiDerivative(Variable variable) throws NotIntegrableException {
throw new NotIntegrableException(this);
}
@Nonnull
public Generic derivative(Variable variable) {
if (isIdentity(variable)) return JsclInteger.valueOf(1);
else return JsclInteger.valueOf(0);
}
public Generic substitute(Variable variable, Generic generic) {
if (isIdentity(variable)) return generic;
else return expressionValue();
}
public Generic expand() {
return expressionValue();
}
public Generic factorize() {
return expressionValue();
}
public Generic elementary() {
return expressionValue();
}
public Generic simplify() {
return expressionValue();
}
public Generic numeric() {
throw new ArithmeticException("Could not evaluate numeric value for technical variable!");
}
public boolean isConstant(Variable variable) {
return !isIdentity(variable);
}
public int compareTo(Variable variable) {
if (this == variable) return 0;
int c = comparator.compare(this, variable);
if (c < 0) return -1;
else if (c > 0) return 1;
else {
TechnicalVariable v = (TechnicalVariable) variable;
c = name.compareTo(v.name);
if (c < 0) return -1;
else if (c > 0) return 1;
else return compareSubscript(subscript, v.subscript);
}
}
public int compareSubscript(int c1[], int c2[]) {
if (c1.length < c2.length) return -1;
else if (c1.length > c2.length) return 1;
for (int i = 0; i < c1.length; i++) {
if (c1[i] < c2[i]) return -1;
else if (c1[i] > c2[i]) return 1;
}
return 0;
}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append(name);
if (subscript.length == 1) buffer.append(subscript[0]);
else for (int i = 0; i < subscript.length; i++) buffer.append("[").append(subscript[i]).append("]");
return buffer.toString();
}
public String toJava() {
return null;
}
public String toMathML(Object data) {
return null;
}
@Nonnull
public Variable newInstance() {
return new TechnicalVariable(name);
}
@Nonnull
@Override
public Set<? extends Constant> getConstants() {
// todo serso: check
return Collections.emptySet();
}
}

View File

@ -0,0 +1,9 @@
package jscl.math;
/**
* User: serso
* Date: 12/26/11
* Time: 10:23 AM
*/
public interface TimeDependent {
}

View File

@ -0,0 +1,271 @@
package jscl.math;
import jscl.math.function.*;
import jscl.math.operator.Factorial;
import jscl.math.operator.Operator;
import jscl.mathml.MathML;
import jscl.text.ParseException;
import org.solovyev.common.Converter;
import org.solovyev.common.math.MathEntity;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public abstract class Variable implements Comparable, MathEntity {
@Nonnull
public static final Comparator<Variable> comparator = VariableComparator.comparator;
protected static final Converter<Generic, Generic> FACTORIZE_CONVERTER = new Converter<Generic, Generic>() {
@Nonnull
@Override
public Generic convert(@Nonnull Generic generic) {
return generic.factorize();
}
};
protected static final Converter<Generic, Generic> ELEMENTARY_CONVERTER = new Converter<Generic, Generic>() {
@Nonnull
@Override
public Generic convert(@Nonnull Generic generic) {
return generic.elementary();
}
};
protected static final Converter<Generic, Generic> EXPAND_CONVERTER = new Converter<Generic, Generic>() {
@Nonnull
@Override
public Generic convert(@Nonnull Generic generic) {
return generic.expand();
}
};
protected static final Converter<Generic, Generic> NUMERIC_CONVERTER = new Converter<Generic, Generic>() {
@Nonnull
@Override
public Generic convert(@Nonnull Generic generic) {
return generic.numeric();
}
};
static final Map<String, String> special = new HashMap<String, String>();
static {
special.put("Alpha", "\u0391");
special.put("Beta", "\u0392");
special.put("Gamma", "\u0393");
special.put("Delta", "\u0394");
special.put("Epsilon", "\u0395");
special.put("Zeta", "\u0396");
special.put("Eta", "\u0397");
special.put("Theta", "\u0398");
special.put("Iota", "\u0399");
special.put("Kappa", "\u039A");
special.put("Lambda", "\u039B");
special.put("Mu", "\u039C");
special.put("Nu", "\u039D");
special.put("Xi", "\u039E");
special.put("Pi", "\u03A0");
special.put("Rho", "\u03A1");
special.put("Sigma", "\u03A3");
special.put("Tau", "\u03A4");
special.put("Upsilon", "\u03A5");
special.put("Phi", "\u03A6");
special.put("Chi", "\u03A7");
special.put("Psi", "\u03A8");
special.put("Omega", "\u03A9");
special.put("alpha", "\u03B1");
special.put("beta", "\u03B2");
special.put("gamma", "\u03B3");
special.put("delta", "\u03B4");
special.put("epsilon", "\u03B5");
special.put("zeta", "\u03B6");
special.put("eta", "\u03B7");
special.put("theta", "\u03B8");
special.put("iota", "\u03B9");
special.put("kappa", "\u03BA");
special.put("lambda", "\u03BB");
special.put("mu", "\u03BC");
special.put("nu", "\u03BD");
special.put("xi", "\u03BE");
special.put("pi", "\u03C0");
special.put("rho", "\u03C1");
special.put("sigma", "\u03C3");
special.put("tau", "\u03C4");
special.put("upsilon", "\u03C5");
special.put("phi", "\u03C6");
special.put("chi", "\u03C7");
special.put("psi", "\u03C8");
special.put("omega", "\u03C9");
special.put("infin", "\u221E");
special.put("nabla", "\u2207");
special.put("aleph", "\u2135");
special.put("hbar", "\u210F");
special.put("hamilt", "\u210B");
special.put("lagran", "\u2112");
special.put("square", "\u25A1");
}
@Nonnull
protected String name;
private Integer id;
private boolean system = true;
public Variable(@Nonnull String name) {
this.name = name;
}
public static Variable valueOf(String str) throws ParseException, NotVariableException {
return Expression.valueOf(str).variableValue();
}
public static Variable[] valueOf(String str[]) throws ParseException, NotVariableException {
int n = str.length;
Variable var[] = new Variable[n];
for (int i = 0; i < n; i++) var[i] = valueOf(str[i]);
return var;
}
@Nonnull
@Override
public Integer getId() {
return id;
}
public void setId(@Nonnull Integer id) {
this.id = id;
}
@Override
public boolean isIdDefined() {
return id != null;
}
@Nonnull
public final String getName() {
return name;
}
public boolean isSystem() {
return system;
}
public void setSystem(boolean system) {
this.system = system;
}
public void copy(@Nonnull MathEntity that) {
if (that instanceof Variable) {
this.name = ((Variable) that).name;
this.id = ((Variable) that).id;
this.system = ((Variable) that).system;
}
}
public abstract Generic antiDerivative(Variable variable) throws NotIntegrableException;
@Nonnull
public abstract Generic derivative(Variable variable);
public abstract Generic substitute(Variable variable, Generic generic);
public abstract Generic expand();
public abstract Generic factorize();
public abstract Generic elementary();
public abstract Generic simplify();
public abstract Generic numeric();
@Nonnull
public Expression expressionValue() {
return Expression.valueOf(this);
}
public abstract boolean isConstant(Variable variable);
public boolean isIdentity(@Nonnull Variable variable) {
return this.compareTo(variable) == 0;
}
public abstract int compareTo(Variable variable);
public int compareTo(Object o) {
return compareTo((Variable) o);
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
return obj instanceof Variable && compareTo((Variable) obj) == 0;
}
public String toString() {
return name;
}
public String toJava() {
return name;
}
public void toMathML(MathML element, @Nullable Object data) {
int exponent = data instanceof Integer ? (Integer) data : 1;
if (exponent == 1) nameToMathML(element);
else {
MathML e1 = element.element("msup");
nameToMathML(e1);
MathML e2 = element.element("mn");
e2.appendChild(element.text(String.valueOf(exponent)));
e1.appendChild(e2);
element.appendChild(e1);
}
}
protected void nameToMathML(MathML element) {
MathML e1 = element.element("mi");
e1.appendChild(element.text(special.containsKey(name) ? special.get(name) : name));
element.appendChild(e1);
}
@Nonnull
public abstract Variable newInstance();
@Nonnull
public abstract Set<? extends Constant> getConstants();
}
class VariableComparator implements Comparator<Variable> {
public static final Comparator<Variable> comparator = new VariableComparator();
private VariableComparator() {
}
static int value(Variable v) {
int n;
if (v instanceof TechnicalVariable) n = 0;
else if (v instanceof IntegerVariable) n = 1;
else if (v instanceof DoubleVariable) n = 2;
else if (v instanceof Fraction && ((Fraction) v).integer()) n = 3;
else if (v instanceof Sqrt && ((Sqrt) v).imaginary()) n = 4;
else if (v instanceof Constant) n = 5;
else if (v instanceof Root) n = 6;
else if (v instanceof Algebraic) n = 7;
else if (v instanceof ImplicitFunction) n = 8;
else if (v instanceof Function) n = 9;
else if (v instanceof Factorial) n = 10;
else if (v instanceof Operator) n = 11;
else if (v instanceof ExpressionVariable) n = 12;
else if (v instanceof VectorVariable) n = 13;
else if (v instanceof MatrixVariable) n = 14;
else throw new ArithmeticException("Forget to add compare object of type: " + v.getClass());
return n;
}
public int compare(Variable o1, Variable o2) {
return value(o1) - value(o2);
}
}

View File

@ -0,0 +1,14 @@
package jscl.math;
import javax.annotation.Nonnull;
public class VectorVariable extends GenericVariable {
public VectorVariable(Generic generic) {
super(generic);
}
@Nonnull
public Variable newInstance() {
return new VectorVariable(null);
}
}

View File

@ -0,0 +1,98 @@
package jscl.math.function;
import jscl.math.*;
import jscl.mathml.MathML;
import javax.annotation.Nonnull;
public class Abs extends Function {
public Abs(Generic generic) {
super("abs", new Generic[]{generic});
}
public Generic antiDerivative(int n) throws NotIntegrableException {
return Constants.Generic.HALF.multiply(parameters[0]).multiply(new Abs(parameters[0]).selfExpand());
}
public Generic derivative(int n) {
return new Sgn(parameters[0]).selfExpand();
}
public Generic selfExpand() {
if (parameters[0].signum() < 0) {
return new Abs(parameters[0].negate()).selfExpand();
}
try {
return parameters[0].integerValue().abs();
} catch (NotIntegerException e) {
}
return expressionValue();
}
public Generic selfElementary() {
return new Sqrt(
parameters[0].pow(2)
).selfElementary();
}
public Generic selfSimplify() {
if (parameters[0].signum() < 0) {
return new Abs(parameters[0].negate()).selfSimplify();
}
try {
return parameters[0].integerValue().abs();
} catch (NotIntegerException e) {
}
try {
Variable v = parameters[0].variableValue();
if (v instanceof Abs) {
Function f = (Function) v;
return f.selfSimplify();
} else if (v instanceof Sgn) {
return JsclInteger.valueOf(1);
}
} catch (NotVariableException e) {
}
return expressionValue();
}
public Generic selfNumeric() {
return parameters[0].abs();
}
public String toJava() {
final StringBuilder result = new StringBuilder();
result.append(parameters[0].toJava());
result.append(".abs()");
return result.toString();
}
public void toMathML(MathML element, Object data) {
int exponent = data instanceof Integer ? (Integer) data : 1;
if (exponent == 1) bodyToMathML(element);
else {
MathML e1 = element.element("msup");
bodyToMathML(e1);
MathML e2 = element.element("mn");
e2.appendChild(element.text(String.valueOf(exponent)));
e1.appendChild(e2);
element.appendChild(e1);
}
}
void bodyToMathML(MathML element) {
MathML e1 = element.element("mfenced");
e1.setAttribute("open", "|");
e1.setAttribute("close", "|");
parameters[0].toMathML(e1, null);
element.appendChild(e1);
}
@Nonnull
public Variable newInstance() {
return new Abs(null);
}
}

View File

@ -0,0 +1,103 @@
package jscl.math.function;
import jscl.math.Generic;
import jscl.math.JsclInteger;
import jscl.mathml.MathML;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 11/12/11
* Time: 3:48 PM
*/
public abstract class AbstractDms extends Algebraic {
protected AbstractDms(@Nonnull String name, Generic degrees, Generic minutes, Generic seconds) {
super(name, new Generic[]{degrees, minutes, seconds});
}
@Nonnull
private static Generic[] createParameters(@Nullable Generic degrees,
@Nullable Generic minutes,
@Nullable Generic seconds) {
final Generic[] result = new Generic[3];
setDefaultValue(result, degrees, 0);
setDefaultValue(result, minutes, 1);
setDefaultValue(result, seconds, 2);
return result;
}
private static void setDefaultValue(@Nonnull Generic[] parameters,
@Nullable Generic parameter,
int position) {
if (parameter == null) {
parameters[position] = JsclInteger.valueOf(0);
} else {
parameters[position] = parameter;
}
}
@Override
public int getMaxParameters() {
return 3;
}
@Override
public void setParameters(@Nullable Generic[] parameters) {
super.setParameters(createParameters(getParameter(parameters, 0), getParameter(parameters, 1), getParameter(parameters, 2)));
}
@Override
public Root rootValue() throws NotRootException {
throw new UnsupportedOperationException("Root for " + name + "() is not supported!");
}
@Override
void bodyToMathML(MathML element, boolean fenced) {
final MathML child = element.element(name);
parameters[0].toMathML(child, null);
// todo serso: add other parameters
element.appendChild(child);
}
@Override
public Generic selfExpand() {
return expressionValue();
}
@Override
public Generic selfElementary() {
return selfExpand();
}
@Override
public Generic selfSimplify() {
return selfExpand();
}
@Override
public Generic selfNumeric() {
Generic degrees = parameters[0];
if (parameters.length > 1 && parameters[1] != null) {
Generic minutes = parameters[1];
degrees = degrees.add(minutes.divide(JsclInteger.valueOf(60)));
}
if (parameters.length > 2 && parameters[2] != null) {
Generic seconds = parameters[2];
degrees = degrees.add(seconds.divide(JsclInteger.valueOf(60 * 60)));
}
return degrees;
}
@Override
public Generic derivative(int n) {
throw new UnsupportedOperationException("Derivative for " + name + "() is not supported!");
}
}

View File

@ -0,0 +1,33 @@
package jscl.math.function;
import jscl.math.Generic;
import jscl.math.NotIntegrableException;
import jscl.mathml.MathML;
public abstract class Algebraic extends Function {
public Algebraic(String name, Generic parameters[]) {
super(name, parameters);
}
public abstract Root rootValue() throws NotRootException;
public Generic antiDerivative(int n) throws NotIntegrableException {
return null;
}
public void toMathML(MathML element, Object data) {
int exponent = data instanceof Integer ? (Integer) data : 1;
if (exponent == 1) bodyToMathML(element, false);
else {
MathML e1 = element.element("msup");
bodyToMathML(e1, true);
MathML e2 = element.element("mn");
e2.appendChild(element.text(String.valueOf(exponent)));
e1.appendChild(e2);
element.appendChild(e1);
}
}
abstract void bodyToMathML(MathML element, boolean fenced);
}

View File

@ -0,0 +1,19 @@
package jscl.math.function;
import jscl.math.Generic;
import jscl.math.NotIntegrableException;
public abstract class ArcTrigonometric extends Function {
public ArcTrigonometric(String name, Generic parameter[]) {
super(name, parameter);
}
public Generic antiDerivative(int n) throws NotIntegrableException {
throw new NotIntegrableException(this);
}
public Generic selfSimplify() {
return selfExpand();
}
}

View File

@ -0,0 +1,106 @@
package jscl.math.function;
import jscl.math.*;
import jscl.mathml.MathML;
import javax.annotation.Nonnull;
import java.util.Arrays;
import java.util.List;
public class Comparison extends Function {
public static final List<String> names = Arrays.asList("eq", "le", "ge", "ne", "lt", "gt", "ap");
private static final String eass[] = {"=", "<=", ">=", "<>", "<", ">", "~"};
private static final String easj[] = {"==", "<=", ">=", "!=", "<", ">", "=="};
private static final String easm[] = {"=", "\u2264", "\u2265", "\u2260", "<", ">", "\u2248"};
int operator;
public Comparison(String name, Generic expression1, Generic expression2) {
super(name, new Generic[]{expression1, expression2});
operator = names.indexOf(name);
if (operator < 0) {
throw new ArithmeticException(name + " comparison function doesn't exist!");
}
}
@Override
public int getMinParameters() {
return 2;
}
public Generic antiDerivative(int n) throws NotIntegrableException {
throw new NotIntegrableException(this);
}
public Generic derivative(int n) {
return JsclInteger.valueOf(0);
}
public Generic selfExpand() {
try {
return compare(parameters[0].integerValue(), parameters[1].integerValue());
} catch (NotIntegerException e) {
}
return expressionValue();
}
public Generic selfElementary() {
return expressionValue();
}
public Generic selfSimplify() {
return expressionValue();
}
public Generic selfNumeric() {
return compare((NumericWrapper) parameters[0], (NumericWrapper) parameters[1]);
}
JsclInteger compare(JsclInteger a1, JsclInteger a2) {
return JsclInteger.valueOf(compare((Generic) a1, a2) ? 1 : 0);
}
NumericWrapper compare(NumericWrapper a1, NumericWrapper a2) {
return new NumericWrapper(JsclInteger.valueOf(compare(a1, (Generic) a2) ? 1 : 0));
}
boolean compare(Generic a1, Generic a2) {
switch (operator) {
case 0:
return a1.compareTo(a2) == 0;
case 1:
return a1.compareTo(a2) <= 0;
case 2:
return a1.compareTo(a2) >= 0;
case 3:
return a1.compareTo(a2) != 0;
case 4:
return a1.compareTo(a2) < 0;
case 5:
return a1.compareTo(a2) > 0;
case 6:
return a1.compareTo(a2) == 0;
default:
return false;
}
}
public String toJava() {
final StringBuilder result = new StringBuilder();
result.append(parameters[0].toJava()).append(easj[operator]).append(parameters[1].toJava());
return result.toString();
}
public void toMathML(MathML element, Object data) {
parameters[0].toMathML(element, null);
MathML e1 = element.element("mo");
e1.appendChild(element.text(easm[operator]));
element.appendChild(e1);
parameters[1].toMathML(element, null);
}
@Nonnull
public Variable newInstance() {
return new Comparison(name, null, null);
}
}

View File

@ -0,0 +1,136 @@
package jscl.math.function;
import jscl.math.*;
import jscl.mathml.MathML;
import javax.annotation.Nonnull;
import static jscl.math.function.Constants.Generic.I;
public class Conjugate extends Function {
public Conjugate(Generic generic) {
super("conjugate", new Generic[]{generic});
}
public Generic antiDerivative(int n) throws NotIntegrableException {
return Constants.Generic.HALF.multiply(selfExpand().pow(2));
}
public Generic derivative(int n) {
return JsclInteger.valueOf(1);
}
public Generic selfExpand() {
try {
return parameters[0].integerValue();
} catch (NotIntegerException e) {
}
if (parameters[0] instanceof Matrix) {
return ((Matrix) parameters[0]).conjugate();
} else if (parameters[0] instanceof JsclVector) {
return ((JsclVector) parameters[0]).conjugate();
}
return expressionValue();
}
public Generic selfElementary() {
try {
return parameters[0].integerValue();
} catch (NotIntegerException e) {
}
return expressionValue();
}
public Generic selfSimplify() {
try {
return parameters[0].integerValue();
} catch (NotIntegerException e) {
}
if (parameters[0].signum() < 0) {
return new Conjugate(parameters[0].negate()).selfSimplify().negate();
} else if (parameters[0].compareTo(I) == 0) {
return I.negate();
}
try {
Variable v = parameters[0].variableValue();
if (v instanceof Conjugate) {
Generic g[] = ((Conjugate) v).getParameters();
return g[0];
} else if (v instanceof Exp) {
Generic g[] = ((Exp) v).getParameters();
return new Exp(new Conjugate(g[0]).selfSimplify()).selfSimplify();
} else if (v instanceof Ln) {
Generic g[] = ((Ln) v).getParameters();
return new Ln(new Conjugate(g[0]).selfSimplify()).selfSimplify();
} else if (v instanceof Lg) {
Generic g[] = ((Lg) v).getParameters();
return new Lg(new Conjugate(g[0]).selfSimplify()).selfSimplify();
}
} catch (NotVariableException e) {
Generic a[] = parameters[0].sumValue();
if (a.length > 1) {
Generic s = JsclInteger.valueOf(0);
for (int i = 0; i < a.length; i++) {
s = s.add(new Conjugate(a[i]).selfSimplify());
}
return s;
} else {
Generic p[] = a[0].productValue();
Generic s = JsclInteger.valueOf(1);
for (int i = 0; i < p.length; i++) {
Power o = p[i].powerValue();
s = s.multiply(new Conjugate(o.value()).selfSimplify().pow(o.exponent()));
}
return s;
}
}
Generic n[] = Fraction.separateCoefficient(parameters[0]);
if (n[0].compareTo(JsclInteger.valueOf(1)) == 0 && n[1].compareTo(JsclInteger.valueOf(1)) == 0) ;
else return new Conjugate(n[2]).selfSimplify().multiply(
new Fraction(n[0], n[1]).selfSimplify()
);
return expressionValue();
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).conjugate();
}
public String toJava() {
StringBuffer buffer = new StringBuffer();
buffer.append(parameters[0].toJava());
buffer.append(".conjugate()");
return buffer.toString();
}
public void toMathML(MathML element, Object data) {
int exponent = data instanceof Integer ? ((Integer) data).intValue() : 1;
if (exponent == 1) bodyToMathML(element);
else {
MathML e1 = element.element("msup");
MathML e2 = element.element("mfenced");
bodyToMathML(e2);
e1.appendChild(e2);
e2 = element.element("mn");
e2.appendChild(element.text(String.valueOf(exponent)));
e1.appendChild(e2);
element.appendChild(e1);
}
}
void bodyToMathML(MathML element) {
MathML e1 = element.element("mover");
parameters[0].toMathML(e1, null);
MathML e2 = element.element("mo");
e2.appendChild(element.text("_"));
e1.appendChild(e2);
element.appendChild(e1);
}
@Nonnull
public Variable newInstance() {
return new Conjugate(null);
}
}

View File

@ -0,0 +1,269 @@
package jscl.math.function;
import jscl.JsclMathEngine;
import jscl.math.*;
import jscl.mathml.MathML;
import jscl.util.ArrayComparator;
import org.solovyev.common.HashCodeBuilder;
import javax.annotation.Nonnull;
import java.util.HashSet;
import java.util.Set;
public class Constant extends Variable {
public static final int PRIME_CHARS = 3;
private int prime;
private Generic subscripts[];
public Constant(String name) {
this(name, 0, new Generic[0]);
}
public Constant(String name, int prime, Generic subscripts[]) {
super(name);
this.prime = prime;
this.subscripts = subscripts;
}
static String primeChars(int n) {
StringBuilder buffer = new StringBuilder();
for (int i = 0; i < n; i++) buffer.append("'");
return buffer.toString();
}
static String underscores(int n) {
StringBuilder buffer = new StringBuilder();
for (int i = 0; i < n; i++) buffer.append("_");
return buffer.toString();
}
static void primeCharsToMathML(MathML element, int n) {
MathML e1 = element.element("mo");
for (int i = 0; i < n; i++) e1.appendChild(element.text("\u2032"));
element.appendChild(e1);
}
public int prime() {
return prime;
}
public Generic[] subscript() {
return subscripts;
}
public Generic antiDerivative(Variable variable) throws NotIntegrableException {
return null;
}
@Nonnull
public Generic derivative(Variable variable) {
if (isIdentity(variable)) {
return JsclInteger.valueOf(1);
} else {
return JsclInteger.valueOf(0);
}
}
public Generic substitute(Variable variable, Generic generic) {
Constant v = (Constant) newInstance();
for (int i = 0; i < subscripts.length; i++) {
v.subscripts[i] = subscripts[i].substitute(variable, generic);
}
if (v.isIdentity(variable)) {
return generic;
} else {
return v.expressionValue();
}
}
public Generic expand() {
Constant v = (Constant) newInstance();
for (int i = 0; i < subscripts.length; i++) {
v.subscripts[i] = subscripts[i].expand();
}
return v.expressionValue();
}
public Generic factorize() {
Constant v = (Constant) newInstance();
for (int i = 0; i < subscripts.length; i++) {
v.subscripts[i] = subscripts[i].factorize();
}
return v.expressionValue();
}
public Generic elementary() {
Constant v = (Constant) newInstance();
for (int i = 0; i < subscripts.length; i++) {
v.subscripts[i] = subscripts[i].elementary();
}
return v.expressionValue();
}
public Generic simplify() {
Constant v = (Constant) newInstance();
for (int i = 0; i < subscripts.length; i++) {
v.subscripts[i] = subscripts[i].simplify();
}
return v.expressionValue();
}
public Generic numeric() {
return new NumericWrapper(this);
}
public boolean isConstant(Variable variable) {
return !isIdentity(variable);
}
public int compareTo(Variable variable) {
if (this == variable) {
return 0;
}
int c = comparator.compare(this, variable);
if (c == 0) {
final Constant that = (Constant) variable;
c = name.compareTo(that.name);
if (c == 0) {
c = ArrayComparator.comparator.compare(this.subscripts, that.subscripts);
if (c == 0) {
if (prime < that.prime) {
return -1;
} else if (prime > that.prime) {
return 1;
} else return 0;
} else {
return c;
}
} else {
return c;
}
} else {
return c;
}
}
@Override
public int hashCode() {
final HashCodeBuilder result = HashCodeBuilder.newInstance();
result.append(Constant.class);
result.append(name);
result.append(subscripts);
result.append(prime);
return result.toHashCode();
}
public String toString() {
final StringBuilder result = new StringBuilder();
result.append(name);
for (Generic subscript : subscripts) {
result.append("[").append(subscript).append("]");
}
if (prime != 0) {
if (prime <= PRIME_CHARS) result.append(primeChars(prime));
else result.append("{").append(prime).append("}");
}
return result.toString();
}
public String toJava() {
final IConstant constantFromRegistry = JsclMathEngine.getInstance().getConstantsRegistry().get(getName());
if (constantFromRegistry != null) {
return constantFromRegistry.toJava();
}
final StringBuilder result = new StringBuilder();
result.append(name);
if (prime != 0) {
if (prime <= PRIME_CHARS) result.append(underscores(prime));
else result.append("_").append(prime);
}
for (Generic subscript : subscripts) {
result.append("[").append(subscript.integerValue().intValue()).append("]");
}
return result.toString();
}
public void toMathML(MathML element, Object data) {
int exponent = data instanceof Integer ? (Integer) data : 1;
if (exponent == 1) bodyToMathML(element);
else {
MathML e1 = element.element("msup");
bodyToMathML(e1);
MathML e2 = element.element("mn");
e2.appendChild(element.text(String.valueOf(exponent)));
e1.appendChild(e2);
element.appendChild(e1);
}
}
public void bodyToMathML(MathML element) {
if (subscripts.length == 0) {
if (prime == 0) {
nameToMathML(element);
} else {
MathML e1 = element.element("msup");
nameToMathML(e1);
primeToMathML(e1);
element.appendChild(e1);
}
} else {
if (prime == 0) {
MathML e1 = element.element("msub");
nameToMathML(e1);
MathML e2 = element.element("mrow");
for (int i = 0; i < subscripts.length; i++) {
subscripts[i].toMathML(e2, null);
}
e1.appendChild(e2);
element.appendChild(e1);
} else {
MathML e1 = element.element("msubsup");
nameToMathML(e1);
MathML e2 = element.element("mrow");
for (int i = 0; i < subscripts.length; i++) {
subscripts[i].toMathML(e2, null);
}
e1.appendChild(e2);
primeToMathML(e1);
element.appendChild(e1);
}
}
}
void primeToMathML(MathML element) {
if (prime <= PRIME_CHARS) {
primeCharsToMathML(element, prime);
} else {
MathML e1 = element.element("mfenced");
MathML e2 = element.element("mn");
e2.appendChild(element.text(String.valueOf(prime)));
e1.appendChild(e2);
element.appendChild(e1);
}
}
@Nonnull
public Variable newInstance() {
return new Constant(name, prime, new Generic[subscripts.length]);
}
@Nonnull
@Override
public Set<? extends Constant> getConstants() {
final Set<Constant> result = new HashSet<Constant>();
result.add(this);
return result;
}
}

View File

@ -0,0 +1,45 @@
package jscl.math.function;
import jscl.math.JsclInteger;
/**
* User: serso
* Date: 1/7/12
* Time: 3:40 PM
*/
public final class Constants {
public static final Constant PI = new Constant("Π");
public static final Constant PI_INV = new Constant("π");
public static final Constant I = new Constant("i");
public static final Constant INF = new Constant("");
public static final Constant INF_2 = new Constant("Infinity");
// not intended for instantiation
private Constants() {
throw new AssertionError();
}
public static class Generic {
public static final jscl.math.Generic E = new Exp(JsclInteger.ONE).expressionValue();
public static final jscl.math.Generic PI = Constants.PI.expressionValue();
public static final jscl.math.Generic PI_INV = Constants.PI_INV.expressionValue();
public static final jscl.math.Generic INF = Constants.INF.expressionValue();
public static final jscl.math.Generic I = new Sqrt(JsclInteger.valueOf(-1)).expressionValue();
// i * PI
public static final jscl.math.Generic I_BY_PI = I.multiply(PI_INV);
// fraction = 1/2
public static final jscl.math.Generic HALF = new Inverse(JsclInteger.valueOf(2)).expressionValue();
// fraction = 1/3
public static final jscl.math.Generic THIRD = new Inverse(JsclInteger.valueOf(3)).expressionValue();
// -1/2 * (1 - i * sqrt (3) )
public static final jscl.math.Generic J = HALF.negate().multiply(JsclInteger.ONE.subtract(I.multiply(new Sqrt(JsclInteger.valueOf(3)).expressionValue())));
// -1/2 * (1 + i * sqrt (3) )
public static final jscl.math.Generic J_BAR = HALF.negate().multiply(JsclInteger.ONE.add(I.multiply(new Sqrt(JsclInteger.valueOf(3)).expressionValue())));
}
}

View File

@ -0,0 +1,33 @@
package jscl.math.function;
import org.solovyev.common.math.AbstractMathRegistry;
/**
* User: serso
* Date: 11/7/11
* Time: 11:59 AM
*/
public class ConstantsRegistry extends AbstractMathRegistry<IConstant> {
public static final String E = "e";
public static final String C = "c";
public static final Double C_VALUE = 299792458d;
public static final String G = "G";
public static final Double G_VALUE = 6.6738480E-11;
public static final String H_REDUCED = "h";
public static final Double H_REDUCED_VALUE = 6.6260695729E-34 / (2 * Math.PI);
public final static String NAN = "NaN";
public ConstantsRegistry() {
this.add(new PiConstant());
this.add(new ExtendedConstant(Constants.PI_INV, Math.PI, null));
this.add(new ExtendedConstant(Constants.INF, Double.POSITIVE_INFINITY, "JsclDouble.valueOf(Double.POSITIVE_INFINITY)"));
this.add(new ExtendedConstant(Constants.INF_2, Double.POSITIVE_INFINITY, "JsclDouble.valueOf(Double.POSITIVE_INFINITY)"));
this.add(new ExtendedConstant(Constants.I, "√(-1)", null));
this.add(new ExtendedConstant(new Constant(E), Math.E, null));
this.add(new ExtendedConstant(new Constant(C), C_VALUE, null));
this.add(new ExtendedConstant(new Constant(G), G_VALUE, null));
this.add(new ExtendedConstant(new Constant(H_REDUCED), H_REDUCED_VALUE, null));
this.add(new ExtendedConstant(new Constant(NAN), Double.NaN, null));
}
}

View File

@ -0,0 +1,95 @@
package jscl.math.function;
import jscl.math.*;
import jscl.mathml.MathML;
import javax.annotation.Nonnull;
public class Cubic extends Algebraic {
public Cubic(Generic generic) {
super("cubic", new Generic[]{generic});
}
public Root rootValue() {
return new Root(
new Generic[]{
parameters[0].negate(),
JsclInteger.valueOf(0),
JsclInteger.valueOf(0),
JsclInteger.valueOf(1)
},
0
);
}
public Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException {
Root r = rootValue();
Generic g[] = r.getParameters();
if (g[0].isPolynomial(variable)) {
return AntiDerivative.compute(r, variable);
} else throw new NotIntegrableException(this);
}
public Generic derivative(int n) {
return Constants.Generic.THIRD.multiply(
new Inverse(
selfExpand().pow(2)
).selfExpand()
);
}
public Generic selfExpand() {
try {
JsclInteger en = parameters[0].integerValue();
if (en.signum() < 0) ;
else {
Generic rt = en.nthrt(3);
if (rt.pow(3).compareTo(en) == 0) return rt;
}
} catch (NotIntegerException e) {
}
return expressionValue();
}
public Generic selfElementary() {
return selfExpand();
}
public Generic selfSimplify() {
try {
JsclInteger en = parameters[0].integerValue();
if (en.signum() < 0) return new Cubic(en.negate()).selfSimplify().negate();
else {
Generic rt = en.nthrt(3);
if (rt.pow(3).compareTo(en) == 0) return rt;
}
} catch (NotIntegerException e) {
}
return expressionValue();
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).nThRoot(3);
}
public String toJava() {
StringBuffer buffer = new StringBuffer();
buffer.append(parameters[0].toJava());
buffer.append(".pow(");
buffer.append(Constants.Generic.THIRD.toJava());
buffer.append(")");
return buffer.toString();
}
void bodyToMathML(MathML element, boolean fenced) {
MathML e1 = element.element("mroot");
parameters[0].toMathML(e1, null);
JsclInteger.valueOf(3).toMathML(e1, null);
element.appendChild(e1);
}
@Nonnull
public Variable newInstance() {
return new Cubic(null);
}
}

View File

@ -0,0 +1,333 @@
package jscl.math.function;
import jscl.CustomFunctionCalculationException;
import jscl.JsclMathEngine;
import jscl.math.*;
import jscl.text.ParseException;
import org.solovyev.common.JBuilder;
import org.solovyev.common.math.MathEntity;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class CustomFunction extends Function implements IFunction {
private static final String LOCAL_VAR_POSTFIX = "_lv_09_03_1988_";
private final static AtomicInteger counter = new AtomicInteger(0);
@Nonnull
private final Integer localVarId;
@Nonnull
private Expression content;
@Nullable
private String description;
@Nonnull
private List<String> parameterNames = Collections.emptyList();
private CustomFunction(@Nonnull String name,
@Nonnull List<String> parameterNames,
@Nonnull Expression content,
@Nullable String description) {
super(name, new Generic[parameterNames.size()]);
this.parameterNames = parameterNames;
this.content = content;
this.description = description;
this.localVarId = counter.incrementAndGet();
}
private CustomFunction(@Nonnull String name,
@Nonnull List<String> parameterNames,
@Nonnull String content,
@Nullable String description) {
super(name, new Generic[parameterNames.size()]);
this.parameterNames = parameterNames;
try {
this.content = Expression.valueOf(content);
} catch (ParseException e) {
throw new CustomFunctionCalculationException(this, e);
}
this.description = description;
this.localVarId = counter.incrementAndGet();
}
@Override
public int getMinParameters() {
return parameterNames == null ? 0 : parameterNames.size();
}
@Override
public int getMaxParameters() {
return parameterNames == null ? Integer.MAX_VALUE: parameterNames.size();
}
@Override
public Generic substitute(@Nonnull Variable variable, @Nonnull Generic generic) {
return super.substitute(variable, generic);
}
@Override
public Generic numeric() {
return selfExpand().numeric();
}
@Override
public Generic expand() {
return selfExpand().expand();
}
@Override
public Generic elementary() {
return selfExpand().elementary();
}
@Override
public Generic factorize() {
return selfExpand().factorize();
}
@Override
public Generic selfExpand() {
Generic localContent = content;
try {
for (String parameterName : parameterNames) {
localContent = localContent.substitute(new Constant(parameterName), Expression.valueOf(new Constant(getParameterNameForConstant(parameterName))));
}
for (int i = 0; i < parameterNames.size(); i++) {
localContent = localContent.substitute(new Constant(getParameterNameForConstant(parameterNames.get(i))), parameters[i]);
}
} finally {
for (String parameterName : parameterNames) {
localContent = localContent.substitute(new Constant(getParameterNameForConstant(parameterName)), Expression.valueOf(new Constant(parameterName)));
}
}
return localContent;
}
@Nonnull
private String getParameterNameForConstant(@Nonnull String parameterName) {
return parameterName + LOCAL_VAR_POSTFIX + "_" + this.localVarId;
}
@Override
public void copy(@Nonnull MathEntity mathEntity) {
super.copy(mathEntity);
if (mathEntity instanceof CustomFunction) {
final CustomFunction that = (CustomFunction) mathEntity;
this.content = that.content;
this.parameterNames = new ArrayList<String>(that.parameterNames);
this.description = that.description;
}
}
@Override
public Generic selfElementary() {
throw new ArithmeticException();
}
@Override
public Generic selfSimplify() {
return expressionValue();
}
@Override
public Generic selfNumeric() {
throw new ArithmeticException();
}
@Override
public Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException {
if (getParameterForAntiDerivation(variable) < 0) {
throw new NotIntegrableException(this);
} else {
return this.content.antiDerivative(variable);
}
}
@Override
public Generic antiDerivative(int n) throws NotIntegrableException {
throw new NotIntegrableException(this);
}
@Nonnull
@Override
public Generic derivative(@Nonnull Variable variable) {
Generic result = JsclInteger.valueOf(0);
for (int i = 0; i < parameters.length; i++) {
// chain rule: f(x) = g(h(x)) => f'(x) = g'(h(x)) * h'(x)
// hd = h'(x)
// gd = g'(x)
final Generic hd = parameters[i].derivative(variable);
final Generic gd = this.content.derivative(variable);
result = result.add(hd.multiply(gd));
}
return result;
}
@Override
public Generic derivative(int n) {
throw new ArithmeticException();
}
@Nonnull
public String getContent() {
return this.content.toString();
}
@Nullable
public String getDescription() {
return this.description;
}
@Nonnull
public List<String> getParameterNames() {
return Collections.unmodifiableList(parameterNames);
}
@Nonnull
@Override
protected String formatUndefinedParameter(int i) {
if (i < this.parameterNames.size()) {
return parameterNames.get(i);
} else {
return super.formatUndefinedParameter(i);
}
}
@Nonnull
@Override
public CustomFunction newInstance() {
return new CustomFunction(name, parameterNames, content, description);
}
public static class Builder implements JBuilder<CustomFunction> {
private final boolean system;
@Nonnull
private String content;
@Nullable
private String description;
@Nonnull
private List<String> parameterNames;
@Nonnull
private String name;
@Nullable
private Integer id;
public Builder(@Nonnull String name,
@Nonnull List<String> parameterNames,
@Nonnull String content) {
this.system = false;
this.content = content;
this.parameterNames = parameterNames;
this.name = name;
}
public Builder(@Nonnull IFunction function) {
this.system = function.isSystem();
this.content = function.getContent();
this.description = function.getDescription();
this.parameterNames = new ArrayList<String>(function.getParameterNames());
this.name = function.getName();
if (function.isIdDefined()) {
this.id = function.getId();
}
}
public Builder() {
this.system = false;
}
public Builder(boolean system,
@Nonnull String name,
@Nonnull List<String> parameterNames,
@Nonnull String content) {
this.system = system;
this.content = content;
this.parameterNames = parameterNames;
this.name = name;
}
@Nonnull
private static String prepareContent(@Nonnull String content) {
final StringBuilder result = new StringBuilder(content.length());
final char groupingSeparator = JsclMathEngine.getInstance().getGroupingSeparator();
for (int i = 0; i < content.length(); i++) {
final char ch = content.charAt(i);
switch (ch) {
case ' ':
case '\'':
case '\n':
case '\r':
// do nothing
break;
default:
// remove grouping separator
if (ch != groupingSeparator) {
result.append(ch);
}
}
}
return result.toString();
}
@Nonnull
public Builder setDescription(@Nullable String description) {
this.description = description;
return this;
}
@Nonnull
public Builder setId(@Nonnull Integer id) {
this.id = id;
return this;
}
@Nonnull
public Builder setContent(@Nonnull String content) {
this.content = content;
return this;
}
@Nonnull
public Builder setParameterNames(@Nonnull List<String> parameterNames) {
this.parameterNames = parameterNames;
return this;
}
@Nonnull
public Builder setName(@Nonnull String name) {
this.name = name;
return this;
}
@Nonnull
public CustomFunction create() {
final CustomFunction customFunction = new CustomFunction(name, parameterNames, prepareContent(content), description);
customFunction.setSystem(system);
if (id != null) {
customFunction.setId(id);
}
return customFunction;
}
}
}

View File

@ -0,0 +1,63 @@
package jscl.math.function;
import jscl.AngleUnit;
import jscl.math.Generic;
import jscl.math.Variable;
import jscl.mathml.MathML;
import javax.annotation.Nonnull;
/**
* User: serso
* Date: 11/12/11
* Time: 4:16 PM
*/
public class Deg extends Algebraic {
public Deg(Generic generic) {
super("deg", new Generic[]{generic});
}
@Override
public Root rootValue() throws NotRootException {
throw new UnsupportedOperationException("Root for deg() is not supported!");
}
@Override
void bodyToMathML(MathML element, boolean fenced) {
final MathML child = element.element("deg");
parameters[0].toMathML(child, null);
element.appendChild(child);
}
@Override
public Generic selfExpand() {
return expressionValue();
}
@Override
public Generic selfElementary() {
return selfExpand();
}
@Override
public Generic selfSimplify() {
return selfExpand();
}
@Override
public Generic selfNumeric() {
return AngleUnit.rad.transform(AngleUnit.deg, parameters[0]);
}
@Override
public Generic derivative(int n) {
throw new UnsupportedOperationException("Derivative for deg() is not supported!");
}
@Nonnull
@Override
public Variable newInstance() {
return new Deg(null);
}
}

View File

@ -0,0 +1,40 @@
package jscl.math.function;
import jscl.math.Generic;
import jscl.math.Variable;
import javax.annotation.Nonnull;
/**
* User: serso
* Date: 11/14/11
* Time: 1:44 PM
*/
public class Dms extends AbstractDms {
public Dms(Generic degrees, Generic minutes, Generic seconds) {
super("dms", degrees, minutes, seconds);
}
@Nonnull
@Override
public Variable newInstance() {
return new Dms(null, null, null);
}
@Nonnull
@Override
protected String formatUndefinedParameter(int i) {
switch (i) {
case 0:
return "d";
case 1:
return "m";
case 2:
return "s";
default:
return super.formatUndefinedParameter(i);
}
}
}

View File

@ -0,0 +1,123 @@
package jscl.math.function;
import jscl.math.*;
import jscl.math.polynomial.Polynomial;
import jscl.mathml.MathML;
import javax.annotation.Nonnull;
public class Exp extends Function {
public Exp(Generic generic) {
super("exp", new Generic[]{generic});
}
public Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException {
Generic s = parameters[0];
if (s.isPolynomial(variable)) {
Polynomial p = Polynomial.factory(variable).valueOf(s);
if (p.degree() == 1) {
Generic a[] = p.elements();
return new Inverse(a[1]).selfExpand().multiply(antiDerivative(0));
} else throw new NotIntegrableException(this);
} else throw new NotIntegrableException(this);
}
public Generic antiDerivative(int n) throws NotIntegrableException {
return selfExpand();
}
public Generic derivative(int n) {
return selfExpand();
}
public Generic selfExpand() {
if (parameters[0].signum() < 0) {
return new Inverse(new Exp(parameters[0].negate()).selfExpand()).selfExpand();
} else if (parameters[0].signum() == 0) {
return JsclInteger.valueOf(1);
}
return expressionValue();
}
public Generic selfElementary() {
return selfExpand();
}
public Generic selfSimplify() {
if (parameters[0].signum() < 0) {
return new Inverse(new Exp(parameters[0].negate()).selfSimplify()).selfSimplify();
} else if (parameters[0].signum() == 0) {
return JsclInteger.valueOf(1);
} else if (parameters[0].compareTo(Constants.Generic.I_BY_PI) == 0) {
return JsclInteger.valueOf(-1);
}
try {
Variable v = parameters[0].variableValue();
if (v instanceof Lg) {
Generic g[] = ((Lg) v).getParameters();
return g[0];
}
} catch (NotVariableException e) {
Generic sumElements[] = parameters[0].sumValue();
if (sumElements.length > 1) {
Generic result = JsclInteger.valueOf(1);
for (Generic sumElement : sumElements) {
result = result.multiply(new Exp(sumElement).selfSimplify());
}
return result;
}
}
Generic n[] = Fraction.separateCoefficient(parameters[0]);
if (n[0].compareTo(JsclInteger.valueOf(1)) == 0 && n[1].compareTo(JsclInteger.valueOf(1)) == 0) ;
else return new Pow(
new Exp(n[2]).selfSimplify(),
new Fraction(n[0], n[1]).selfSimplify()
).selfSimplify();
return expressionValue();
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).exp();
}
public void toMathML(MathML element, Object data) {
int exponent = data instanceof Integer ? ((Integer) data).intValue() : 1;
if (exponent == 1) bodyToMathML(element, false);
else {
MathML e1 = element.element("msup");
bodyToMathML(e1, true);
MathML e2 = element.element("mn");
e2.appendChild(element.text(String.valueOf(exponent)));
e1.appendChild(e2);
element.appendChild(e1);
}
}
void bodyToMathML(MathML element, boolean fenced) {
if (fenced) {
MathML e1 = element.element("mfenced");
bodyToMathML(e1);
element.appendChild(e1);
} else {
bodyToMathML(element);
}
}
void bodyToMathML(MathML element) {
MathML e1 = element.element("msup");
MathML e2 = element.element("mi");
e2.appendChild(element.text(/*"\u2147"*/"e"));
e1.appendChild(e2);
parameters[0].toMathML(e1, null);
element.appendChild(e1);
}
@Nonnull
public Variable newInstance() {
return new Exp(null);
}
}

View File

@ -0,0 +1,226 @@
package jscl.math.function;
import org.solovyev.common.JBuilder;
import org.solovyev.common.math.MathEntity;
import org.solovyev.common.text.Strings;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 11/7/11
* Time: 12:06 PM
*/
public class ExtendedConstant implements Comparable<ExtendedConstant>, IConstant {
@Nonnull
private Constant constant;
@Nullable
private String value;
@Nullable
private String javaString;
@Nullable
private String description;
ExtendedConstant() {
}
ExtendedConstant(@Nonnull Constant constant,
@Nullable String value,
@Nullable String javaString) {
this.constant = constant;
this.value = value;
this.javaString = javaString;
}
ExtendedConstant(@Nonnull Constant constant,
@Nullable Double value,
@Nullable String javaString) {
this.constant = constant;
this.value = value == null ? null : String.valueOf(value);
this.javaString = javaString;
}
@Nonnull
public static String toString(@Nonnull IConstant constant) {
final Double doubleValue = constant.getDoubleValue();
if (doubleValue == null) {
final String stringValue = constant.getValue();
if (!Strings.isEmpty(stringValue)) {
return constant.getName() + " = " + stringValue;
} else {
return constant.getName();
}
} else {
return constant.getName() + " = " + doubleValue;
}
}
@Nonnull
@Override
public String getName() {
return this.constant.getName();
}
@Override
public boolean isSystem() {
return this.constant.isSystem();
}
@Nonnull
@Override
public Integer getId() {
return constant.getId();
}
@Override
public void setId(@Nonnull Integer id) {
constant.setId(id);
}
@Override
public boolean isIdDefined() {
return constant.isIdDefined();
}
@Override
public void copy(@Nonnull MathEntity that) {
this.constant.copy(that);
if (that instanceof IConstant) {
this.description = ((IConstant) that).getDescription();
this.value = ((IConstant) that).getValue();
}
if (that instanceof ExtendedConstant) {
this.javaString = ((ExtendedConstant) that).javaString;
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ExtendedConstant)) return false;
ExtendedConstant that = (ExtendedConstant) o;
if (!constant.equals(that.constant)) return false;
return true;
}
@Override
public int hashCode() {
return constant.hashCode();
}
@Override
@Nonnull
public Constant getConstant() {
return constant;
}
@Override
@Nullable
public String getDescription() {
return description;
}
@Override
public boolean isDefined() {
return value != null;
}
@Override
@Nullable
public String getValue() {
return value;
}
@Override
public Double getDoubleValue() {
Double result = null;
if (value != null) {
try {
result = Double.valueOf(value);
} catch (NumberFormatException e) {
// do nothing - string is not a double
}
}
return result;
}
@Override
@Nonnull
public String toJava() {
if (javaString != null) {
return javaString;
} else if (value != null) {
return String.valueOf(value);
} else {
return constant.getName();
}
}
@Override
public String toString() {
return toString(this);
}
@Override
public int compareTo(ExtendedConstant o) {
return this.constant.compareTo(o.getConstant());
}
public static final class Builder implements JBuilder<ExtendedConstant> {
@Nonnull
private Constant constant;
@Nullable
private String value;
@Nullable
private String javaString;
@Nullable
private String description;
public Builder(@Nonnull Constant constant, @Nullable Double value) {
this(constant, value == null ? null : String.valueOf(value));
}
public Builder(@Nonnull Constant constant, @Nullable String value) {
this.constant = constant;
this.value = value;
}
public Builder setJavaString(@Nullable String javaString) {
this.javaString = javaString;
return this;
}
public Builder setDescription(@Nullable String description) {
this.description = description;
return this;
}
@Nonnull
@Override
public ExtendedConstant create() {
final ExtendedConstant result = new ExtendedConstant();
result.constant = constant;
result.value = value;
result.javaString = javaString;
result.description = description;
return result;
}
}
}

View File

@ -0,0 +1,186 @@
package jscl.math.function;
import jscl.math.*;
import jscl.mathml.MathML;
import javax.annotation.Nonnull;
public class Fraction extends Algebraic {
// fraction: n/d
// where n = numerator,
// d = denominator
public Fraction(Generic numerator, Generic denominator) {
super("frac", new Generic[]{numerator, denominator});
}
/**
* @param generic any generic value
* @return array of 3 elements where
* a[0] =
*/
static Generic[] separateCoefficient(@Nonnull Generic generic) {
if (generic.signum() < 0) {
Generic n[] = separateCoefficient(generic.negate());
return new Generic[]{n[0], n[1], n[2].negate()};
}
try {
final Variable v = generic.variableValue();
if (v instanceof Fraction) {
final Generic parameters[] = ((Fraction) v).getParameters();
// v = n / d
// numerator
final Generic n = parameters[0].expressionValue();
// denumerator
final Generic d = parameters[1].expressionValue();
// na = [gcd(n), n/(gcd(n))]
Generic na[] = n.gcdAndNormalize();
// nd = [gcd(d), d/(gcd(d))]
Generic nd[] = d.gcdAndNormalize();
return new Generic[]{na[0], nd[0], new Fraction(na[1], nd[1]).selfExpand()};
}
} catch (NotVariableException e) {
try {
Generic a = generic.expressionValue();
Generic n[] = a.gcdAndNormalize();
return new Generic[]{n[0], JsclInteger.valueOf(1), n[1]};
} catch (NotExpressionException e2) {
}
}
return new Generic[]{JsclInteger.valueOf(1), JsclInteger.valueOf(1), generic};
}
@Override
public int getMinParameters() {
return 2;
}
public Root rootValue() {
return new Root(new Generic[]{parameters[0].negate(), parameters[1]}, 0);
}
public Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException {
if (parameters[0].isPolynomial(variable) && parameters[1].isPolynomial(variable)) {
return AntiDerivative.compute(this, variable);
} else throw new NotIntegrableException(this);
}
public Generic derivative(int n) {
if (n == 0) {
return new Inverse(parameters[1]).selfExpand();
} else {
return parameters[0].multiply(new Inverse(parameters[1]).selfExpand().pow(2).negate());
}
}
public boolean integer() {
try {
if (parameters[0] != null && parameters[1] != null) {
parameters[0].integerValue().intValue();
parameters[1].integerValue().intValue();
return true;
}
} catch (NotIntegerException e) {
}
return false;
}
public Generic selfExpand() {
if (parameters[0].compareTo(JsclInteger.valueOf(1)) == 0) {
return new Inverse(parameters[1]).selfExpand();
}
try {
return parameters[0].divide(parameters[1]);
} catch (NotDivisibleException e) {
} catch (ArithmeticException e) {
}
return expressionValue();
}
public Generic selfElementary() {
return selfExpand();
}
public Generic selfSimplify() {
if (parameters[0].signum() < 0) {
return new Fraction(parameters[0].negate(), parameters[1]).selfSimplify().negate();
}
if (parameters[1].signum() < 0) {
return new Fraction(parameters[0].negate(), parameters[1].negate()).selfSimplify();
}
return selfExpand();
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).divide((NumericWrapper) parameters[1]);
}
public String toString() {
final StringBuilder result = new StringBuilder();
try {
parameters[0].powerValue();
result.append(parameters[0]);
} catch (NotPowerException e) {
result.append(GenericVariable.valueOf(parameters[0]));
}
result.append("/");
try {
final Variable v = parameters[1].variableValue();
if (v instanceof Fraction) {
result.append(GenericVariable.valueOf(parameters[1]));
} else {
result.append(v);
}
} catch (NotVariableException e) {
try {
parameters[1].abs().powerValue();
result.append(parameters[1]);
} catch (NotPowerException e2) {
result.append(GenericVariable.valueOf(parameters[1]));
}
}
return result.toString();
}
public String toJava() {
final StringBuilder result = new StringBuilder();
result.append(parameters[0].toJava());
result.append(".divide(");
result.append(parameters[1].toJava());
result.append(")");
return result.toString();
}
void bodyToMathML(MathML element, boolean fenced) {
if (fenced) {
MathML e1 = element.element("mfenced");
bodyToMathML(e1);
element.appendChild(e1);
} else {
bodyToMathML(element);
}
}
void bodyToMathML(MathML element) {
MathML e1 = element.element("mfrac");
parameters[0].toMathML(e1, null);
parameters[1].toMathML(e1, null);
element.appendChild(e1);
}
@Nonnull
public Variable newInstance() {
return new Fraction(null, null);
}
}

View File

@ -0,0 +1,101 @@
package jscl.math.function;
import jscl.math.Generic;
import jscl.math.JsclInteger;
import jscl.math.NotIntegrableException;
import jscl.math.Variable;
import jscl.math.operator.AbstractFunction;
import jscl.text.ParserUtils;
import org.solovyev.common.math.MathEntity;
import javax.annotation.Nonnull;
public abstract class Function extends AbstractFunction {
protected Function(String name, Generic parameters[]) {
super(name, parameters);
}
public int getMinParameters() {
return 1;
}
@Override
public void copy(@Nonnull MathEntity that) {
super.copy(that);
if (that instanceof Function) {
if (((Function) that).parameters != null) {
this.parameters = ParserUtils.copyOf(((Function) that).parameters);
} else {
this.parameters = null;
}
}
}
public Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException {
final int parameter = getParameterForAntiDerivation(variable);
if (parameter < 0) {
throw new NotIntegrableException(this);
} else {
return antiDerivative(parameter);
}
}
protected int getParameterForAntiDerivation(@Nonnull Variable variable) {
int result = -1;
for (int i = 0; i < parameters.length; i++) {
if (result == -1 && parameters[i].isIdentity(variable)) {
// found!
result = i;
} else if (!parameters[i].isConstant(variable)) {
result = -1;
break;
}
}
return result;
}
public abstract Generic antiDerivative(int n) throws NotIntegrableException;
@Nonnull
public Generic derivative(@Nonnull Variable variable) {
if (isIdentity(variable)) {
return JsclInteger.valueOf(1);
} else {
Generic result = JsclInteger.valueOf(0);
for (int i = 0; i < parameters.length; i++) {
// chain rule: f(x) = g(h(x)) => f'(x) = g'(h(x)) * h'(x)
// hd = h'(x)
// gd = g'(x)
final Generic hd = parameters[i].derivative(variable);
final Generic gd = this.derivative(i);
result = result.add(hd.multiply(gd));
}
return result;
}
}
public abstract Generic derivative(int n);
public boolean isConstant(Variable variable) {
boolean result = !isIdentity(variable);
if (result) {
for (Generic parameter : parameters) {
if (!parameter.isConstant(variable)) {
result = false;
break;
}
}
}
return result;
}
}

View File

@ -0,0 +1,81 @@
package jscl.math.function;
import jscl.math.Variable;
import jscl.math.function.hyperbolic.*;
import jscl.math.function.trigonometric.*;
import org.solovyev.common.math.AbstractMathRegistry;
import javax.annotation.Nonnull;
/**
* User: serso
* Date: 10/29/11
* Time: 12:54 PM
*/
public class FunctionsRegistry extends AbstractMathRegistry<Function> {
private final static FunctionsRegistry instance = new FunctionsRegistry();
static {
instance.add(new Deg(null));
instance.add(new Rad(null, null, null));
instance.add(new Dms(null, null, null));
instance.add(new Sin(null));
instance.add(new Cos(null));
instance.add(new Tan(null));
instance.add(new Cot(null));
instance.add(new Asin(null));
instance.add(new Acos(null));
instance.add(new Atan(null));
instance.add(new Acot(null));
instance.add(new Ln(null));
instance.add(new Lg(null));
instance.add(new Exp(null));
instance.add(new Sqrt(null));
instance.add(new Cubic(null));
instance.add(new Sinh(null));
instance.add(new Cosh(null));
instance.add(new Tanh(null));
instance.add(new Coth(null));
instance.add(new Asinh(null));
instance.add(new Acosh(null));
instance.add(new Atanh(null));
instance.add(new Acoth(null));
instance.add(new Abs(null));
instance.add(new Sgn(null));
instance.add(new Conjugate(null));
for (String name : Comparison.names) {
instance.add(new Comparison(name, null, null));
}
}
@Nonnull
public static FunctionsRegistry getInstance() {
return instance;
}
@Nonnull
public static <T extends Variable> T copy(@Nonnull T variable) {
final T result = (T) variable.newInstance();
if (variable.isIdDefined()) {
result.setId(variable.getId());
}
result.setSystem(variable.isSystem());
return result;
}
@Override
public Function get(@Nonnull String name) {
final Function function = super.get(name);
return function == null ? null : copy(function);
}
}

View File

@ -0,0 +1,31 @@
package jscl.math.function;
import org.solovyev.common.math.MathEntity;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 11/10/11
* Time: 6:01 PM
*/
public interface IConstant extends MathEntity {
@Nonnull
Constant getConstant();
@Nullable
String getDescription();
boolean isDefined();
@Nullable
String getValue();
@Nullable
Double getDoubleValue();
@Nonnull
String toJava();
}

View File

@ -0,0 +1,21 @@
package jscl.math.function;
import org.solovyev.common.math.MathEntity;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
public interface IFunction extends MathEntity {
@Nonnull
String getContent();
@Nullable
String getDescription();
String toJava();
@Nonnull
List<String> getParameterNames();
}

View File

@ -0,0 +1,273 @@
package jscl.math.function;
import jscl.math.Generic;
import jscl.math.NotIntegrableException;
import jscl.math.Variable;
import jscl.mathml.MathML;
import jscl.util.ArrayComparator;
import javax.annotation.Nonnull;
public class ImplicitFunction extends Function {
private int derivations[];
private Generic subscripts[];
public ImplicitFunction(String name, Generic parameter[], int derivations[], Generic subscripts[]) {
super(name, parameter);
this.derivations = derivations;
this.subscripts = subscripts;
}
static int compareDerivation(int c1[], int c2[]) {
int n = c1.length;
for (int i = n - 1; i >= 0; i--) {
if (c1[i] < c2[i]) return -1;
else if (c1[i] > c2[i]) return 1;
}
return 0;
}
public Generic antiDerivative(int n) throws NotIntegrableException {
int c[] = new int[derivations.length];
for (int i = 0; i < c.length; i++) {
if (i == n) {
if (derivations[i] > 0) c[i] = derivations[i] - 1;
else throw new NotIntegrableException(this);
} else c[i] = derivations[i];
}
return new ImplicitFunction(name, parameters, c, subscripts).selfExpand();
}
public Generic derivative(int n) {
int c[] = new int[derivations.length];
for (int i = 0; i < c.length; i++) {
if (i == n) c[i] = derivations[i] + 1;
else c[i] = derivations[i];
}
return new ImplicitFunction(name, parameters, c, subscripts).selfExpand();
}
public Generic selfExpand() {
return expressionValue();
}
public Generic selfElementary() {
return expressionValue();
}
public Generic selfSimplify() {
return expressionValue();
}
/*@Override
public Generic numeric() {
return evaluateNumerically();
}*/
public Generic selfNumeric() {
throw new ArithmeticException();
/*Function function = FunctionsRegistry.getInstance().get(this.name);
Generic result;
if ( function == null ) {
throw new ArithmeticException();
} else {
function.setParameters(this.parameters);
result = function;
for (int derivation : derivations) {
for ( int i = 0; i < derivation; i++ ) {
result = result.derivative(derivation);
}
}
result = result.numeric();
}
return result;*/
}
public int compareTo(Variable that) {
if (this == that) return 0;
int c = comparator.compare(this, that);
if (c < 0) return -1;
else if (c > 0) return 1;
else {
ImplicitFunction v = (ImplicitFunction) that;
c = name.compareTo(v.name);
if (c < 0) return -1;
else if (c > 0) return 1;
else {
c = ArrayComparator.comparator.compare(subscripts, v.subscripts);
if (c < 0) return -1;
else if (c > 0) return 1;
else {
c = compareDerivation(derivations, v.derivations);
if (c < 0) return -1;
else if (c > 0) return 1;
else return ArrayComparator.comparator.compare(parameters, v.parameters);
}
}
}
}
public String toString() {
final StringBuilder result = new StringBuilder();
int n = 0;
for (int derivation : derivations) {
n += derivation;
}
result.append(name);
for (Generic aSubscript : subscripts) {
result.append("[").append(aSubscript).append("]");
}
if (n == 0) {
// do nothing
} else if (parameters.length == 1 && n <= Constant.PRIME_CHARS) {
result.append(Constant.primeChars(n));
} else {
result.append(derivationToString());
}
result.append("(");
for (int i = 0; i < parameters.length; i++) {
result.append(parameters[i]).append(i < parameters.length - 1 ? ", " : "");
}
result.append(")");
return result.toString();
}
String derivationToString() {
StringBuilder buffer = new StringBuilder();
buffer.append("{");
for (int i = 0; i < derivations.length; i++) {
buffer.append(derivations[i]).append(i < derivations.length - 1 ? ", " : "");
}
buffer.append("}");
return buffer.toString();
}
public String toJava() {
final StringBuilder result = new StringBuilder();
int n = 0;
for (int derivation : derivations) {
n += derivation;
}
result.append(name);
if (n == 0) {
// do nothing
} else if (parameters.length == 1 && n <= Constant.PRIME_CHARS) {
result.append(Constant.underscores(n));
} else {
result.append(derivationToJava());
}
result.append("(");
for (int i = 0; i < parameters.length; i++) {
result.append(parameters[i].toJava()).append(i < parameters.length - 1 ? ", " : "");
}
result.append(")");
for (Generic subscript : subscripts) {
result.append("[").append(subscript.integerValue().intValue()).append("]");
}
return result.toString();
}
String derivationToJava() {
StringBuilder buffer = new StringBuilder();
for (int i = 0; i < derivations.length; i++) {
buffer.append("_").append(derivations[i]);
}
return buffer.toString();
}
public void toMathML(MathML element, Object data) {
MathML e1;
int exponent = data instanceof Integer ? (Integer) data : 1;
if (exponent == 1) bodyToMathML(element);
else {
e1 = element.element("msup");
bodyToMathML(e1);
MathML e2 = element.element("mn");
e2.appendChild(element.text(String.valueOf(exponent)));
e1.appendChild(e2);
element.appendChild(e1);
}
e1 = element.element("mfenced");
for (Generic parameter : parameters) {
parameter.toMathML(e1, null);
}
element.appendChild(e1);
}
void bodyToMathML(MathML element) {
int n = 0;
for (int derivation : derivations) {
n += derivation;
}
if (subscripts.length == 0) {
if (n == 0) {
nameToMathML(element);
} else {
MathML e1 = element.element("msup");
nameToMathML(e1);
derivationToMathML(e1, n);
element.appendChild(e1);
}
} else {
if (n == 0) {
MathML e1 = element.element("msub");
nameToMathML(e1);
MathML e2 = element.element("mrow");
for (Generic subscript : subscripts) {
subscript.toMathML(e2, null);
}
e1.appendChild(e2);
element.appendChild(e1);
} else {
MathML e1 = element.element("msubsup");
nameToMathML(e1);
MathML e2 = element.element("mrow");
for (Generic subscript : subscripts) {
subscript.toMathML(e2, null);
}
e1.appendChild(e2);
derivationToMathML(e1, n);
element.appendChild(e1);
}
}
}
void derivationToMathML(MathML element, int n) {
if (parameters.length == 1 && n <= Constant.PRIME_CHARS) {
Constant.primeCharsToMathML(element, n);
} else {
MathML e1 = element.element("mfenced");
for (int derivation : derivations) {
MathML e2 = element.element("mn");
e2.appendChild(element.text(String.valueOf(derivation)));
e1.appendChild(e2);
}
element.appendChild(e1);
}
}
@Nonnull
public Variable newInstance() {
return new ImplicitFunction(name, new Generic[parameters.length], derivations, subscripts);
}
}

View File

@ -0,0 +1,43 @@
package jscl.math.function;
import jscl.math.Generic;
import jscl.math.JsclInteger;
import jscl.math.NotDivisibleException;
import jscl.math.Variable;
import javax.annotation.Nonnull;
public class Inverse extends Fraction {
// inverse function: 1/g
public Inverse(Generic generic) {
super(JsclInteger.valueOf(1), generic);
}
public Generic selfExpand() {
try {
Generic parameter = parameter();
/*try {
if (JsclInteger.ZERO.equals(parameter.integerValue())) {
throw new ArithmeticException("Division by 0!");
}
} catch (NotIntegerException e) {
// ok
}*/
return JsclInteger.ONE.divide(parameter);
} catch (NotDivisibleException e) {
}
return expressionValue();
}
public Generic parameter() {
return parameters[1];
}
@Nonnull
public Variable newInstance() {
return new Inverse(null);
}
}

View File

@ -0,0 +1,86 @@
package jscl.math.function;
import jscl.math.*;
import javax.annotation.Nonnull;
import static jscl.math.JsclInteger.ONE;
import static jscl.math.JsclInteger.ZERO;
public class Lg extends Function {
public Lg(Generic generic) {
super("lg", new Generic[]{generic});
}
public Generic antiDerivative(int n) throws NotIntegrableException {
// tmp = ln(x) - 1
final Generic tmp = new Ln(parameters[0]).expressionValue().subtract(ONE);
// ln10 = ln (10)
final Generic ln10 = new Ln(JsclInteger.valueOf(10L)).expressionValue();
return new Fraction(parameters[0].multiply(tmp), ln10).expressionValue();
}
public Generic derivative(int n) {
return new Inverse(parameters[0].multiply(new Ln(JsclInteger.valueOf(10L)).expressionValue())).expressionValue();
}
public Generic selfExpand() {
if (parameters[0].compareTo(JsclInteger.valueOf(1)) == 0) {
return JsclInteger.valueOf(0);
}
return expressionValue();
}
public Generic selfElementary() {
return selfExpand();
}
public Generic selfSimplify() {
Generic coefficents[] = Fraction.separateCoefficient(parameters[0]);
final Generic a = coefficents[0];
final Generic b = coefficents[1];
final Generic c = coefficents[2];
final boolean aOne = a.compareTo(ONE) == 0;
final boolean bOne = b.compareTo(ONE) == 0;
final boolean cOne = c.compareTo(ONE) == 0;
if (aOne && bOne && cOne) {
return ZERO;
} else {
if (aOne && bOne) {
return expressionValue();
} else if (bOne && cOne) {
return expressionValue();
} else {
// lg ( a * c / b ) = lg ( c ) + lg( a ) - lg (b)
final Generic lga = lg(a, aOne);
final Generic lgb = lg(b, bOne);
final Generic lgc = lg(c, cOne);
return lgc.add(lga).subtract(lgb);
}
}
}
private Generic lg(Generic a, boolean aOne) {
Generic lga;
if (aOne) {
lga = ZERO;
} else {
lga = new Lg(a).selfSimplify();
}
return lga;
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).lg();
}
@Nonnull
public Variable newInstance() {
return new Lg(null);
}
}

View File

@ -0,0 +1,75 @@
package jscl.math.function;
import jscl.math.*;
import javax.annotation.Nonnull;
public class Ln extends Function {
public Ln(Generic generic) {
super("ln", new Generic[]{generic});
}
public Generic antiDerivative(int n) throws NotIntegrableException {
return parameters[0].multiply(new Ln(parameters[0]).selfExpand().subtract(JsclInteger.ONE));
}
public Generic derivative(int n) {
return new Inverse(parameters[0]).selfExpand();
}
public Generic selfExpand() {
if (parameters[0].compareTo(JsclInteger.valueOf(1)) == 0) {
return JsclInteger.valueOf(0);
}
return expressionValue();
}
public Generic selfElementary() {
return selfExpand();
}
public Generic selfSimplify() {
try {
JsclInteger en = parameters[0].integerValue();
if (en.signum() < 0) {
return Constants.Generic.I_BY_PI.add(new Ln(en.negate()).selfSimplify());
} else {
Generic a = en.factorize();
Generic p[] = a.productValue();
Generic s = JsclInteger.valueOf(0);
for (int i = 0; i < p.length; i++) {
Power o = p[i].powerValue();
s = s.add(JsclInteger.valueOf(o.exponent()).multiply(new Ln(o.value(true)).expressionValue()));
}
return s;
}
} catch (NotIntegerException e) {
}
try {
Variable v = parameters[0].variableValue();
if (v instanceof Sqrt) {
Generic g[] = ((Sqrt) v).getParameters();
return Constants.Generic.HALF.multiply(new Ln(g[0]).selfSimplify());
}
} catch (NotVariableException e) {
}
Generic n[] = Fraction.separateCoefficient(parameters[0]);
if (n[0].compareTo(JsclInteger.valueOf(1)) == 0 && n[1].compareTo(JsclInteger.valueOf(1)) == 0) ;
else return new Ln(n[2]).selfSimplify().add(
new Ln(n[0]).selfSimplify()
).subtract(
new Ln(n[1]).selfSimplify()
);
return expressionValue();
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).ln();
}
@Nonnull
public Variable newInstance() {
return new Ln(null);
}
}

View File

@ -0,0 +1,10 @@
package jscl.math.function;
public class NotRootException extends ArithmeticException {
public NotRootException() {
}
public NotRootException(String s) {
super(s);
}
}

View File

@ -0,0 +1,29 @@
package jscl.math.function;
import jscl.AngleUnit;
import jscl.JsclMathEngine;
/**
* User: serso
* Date: 11/29/11
* Time: 11:28 AM
*/
public class PiConstant extends ExtendedConstant {
public PiConstant() {
super(Constants.PI, Math.PI, "JsclDouble.valueOf(Math.PI)");
}
@Override
public Double getDoubleValue() {
Double result = null;
try {
result = AngleUnit.rad.transform(JsclMathEngine.getInstance().getAngleUnits(), Double.valueOf(getValue()));
} catch (NumberFormatException e) {
// do nothing - string is not a double
}
return result;
}
}

View File

@ -0,0 +1,43 @@
package jscl.math.function;
import jscl.math.Generic;
import jscl.math.operator.*;
import org.solovyev.common.math.AbstractMathRegistry;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 10/31/11
* Time: 10:56 PM
*/
public class PostfixFunctionsRegistry extends AbstractMathRegistry<Operator> {
private final static PostfixFunctionsRegistry instance = new PostfixFunctionsRegistry();
static {
instance.add(new DoubleFactorial(null));
instance.add(new Factorial(null));
instance.add(new Degree(null));
instance.add(new Percent(null, null));
}
@Nonnull
public static PostfixFunctionsRegistry getInstance() {
return instance;
}
@Nullable
public Operator get(@Nonnull String name, @Nonnull Generic[] parameters) {
final Operator operator = super.get(name);
return operator == null ? null : operator.newInstance(parameters);
}
@Override
public Operator get(@Nonnull String name) {
final Operator operator = super.get(name);
return operator == null ? null : FunctionsRegistry.copy(operator);
}
}

View File

@ -0,0 +1,289 @@
package jscl.math.function;
import jscl.math.*;
import jscl.mathml.MathML;
import javax.annotation.Nonnull;
import static jscl.math.JsclInteger.ONE;
import static jscl.math.JsclInteger.ZERO;
public class Pow extends Algebraic {
private static final int MAX_ARRAY_SIZE = 10000;
public Pow(Generic generic, Generic exponent) {
super("pow", new Generic[]{generic, exponent});
}
static Generic root_minus_1(int d) {
switch (d) {
case 1:
return JsclInteger.valueOf(-1);
case 2:
return Constants.Generic.I;
case 3:
return Constants.Generic.J_BAR.negate();
case 4:
return new Sqrt(Constants.Generic.HALF).expressionValue().multiply(JsclInteger.valueOf(1).add(Constants.Generic.I));
case 6:
return Constants.Generic.HALF.multiply(new Sqrt(JsclInteger.valueOf(3)).expressionValue().add(Constants.Generic.I));
default:
return null;
}
}
@Override
public int getMinParameters() {
return 2;
}
public Root rootValue() throws NotRootException {
try {
Variable v = parameters[1].variableValue();
if (v instanceof Inverse) {
Generic g = ((Inverse) v).parameter();
try {
int d = g.integerValue().intValue();
if (d > 0 && d < MAX_ARRAY_SIZE) {
Generic a[] = new Generic[d + 1];
a[0] = parameters[0].negate();
for (int i = 1; i < d; i++) {
a[i] = ZERO;
}
a[d] = ONE;
return new Root(a, 0);
}
} catch (NotIntegerException e) {
}
}
} catch (NotVariableException e) {
}
throw new NotRootException();
}
public Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException {
try {
Root r = rootValue();
Generic g[] = r.getParameters();
if (g[0].isPolynomial(variable)) {
return AntiDerivative.compute(r, variable);
} else throw new NotIntegrableException(this);
} catch (NotRootException e) {
}
return super.antiDerivative(variable);
}
public Generic antiDerivative(int n) throws NotIntegrableException {
if (n == 0) {
return new Pow(parameters[0], parameters[1].add(JsclInteger.valueOf(1))).selfExpand().multiply(new Inverse(parameters[1].add(JsclInteger.valueOf(1))).selfExpand());
} else {
return new Pow(parameters[0], parameters[1]).selfExpand().multiply(new Inverse(new Ln(parameters[0]).selfExpand()).selfExpand());
}
}
public Generic derivative(int n) {
if (n == 0) {
return new Pow(parameters[0], parameters[1].subtract(JsclInteger.valueOf(1))).selfExpand().multiply(parameters[1]);
} else {
return new Pow(parameters[0], parameters[1]).selfExpand().multiply(new Ln(parameters[0]).selfExpand());
}
}
public Generic selfExpand() {
if (parameters[0].compareTo(JsclInteger.valueOf(1)) == 0) {
return JsclInteger.valueOf(1);
}
if (parameters[1].signum() < 0) {
return new Pow(new Inverse(parameters[0]).selfExpand(), parameters[1].negate()).selfExpand();
}
try {
int c = parameters[1].integerValue().intValue();
return parameters[0].pow(c);
} catch (NotIntegerException e) {
}
try {
Root r = rootValue();
int d = r.degree();
Generic g[] = r.getParameters();
Generic a = g[0].negate();
try {
JsclInteger en = a.integerValue();
if (en.signum() < 0) ;
else {
Generic rt = en.nthrt(d);
if (rt.pow(d).compareTo(en) == 0) return rt;
}
} catch (NotIntegerException e) {
}
} catch (NotRootException e) {
}
return expressionValue();
}
public Generic selfElementary() {
return new Exp(
new Ln(
parameters[0]
).selfElementary().multiply(
parameters[1]
)
).selfElementary();
}
public Generic selfSimplify() {
// a ^ b
// a = 1 => for any b: 1 ^ b = 1
if (parameters[0].compareTo(ONE) == 0) {
return JsclInteger.valueOf(1);
}
// b < 0 => a ^ b = (1 / a) ^ (-b)
if (parameters[1].signum() < 0) {
return new Pow(new Inverse(parameters[0]).selfSimplify(), parameters[1].negate()).selfSimplify();
}
try {
// if b is integer => just calculate the result
int intPower = parameters[1].integerValue().intValue();
return parameters[0].pow(intPower);
} catch (NotIntegerException e) {
}
try {
Root r = rootValue();
int d = r.degree();
Generic g[] = r.getParameters();
Generic a = g[0].negate();
try {
JsclInteger en = a.integerValue();
if (en.signum() < 0) ;
else {
Generic rt = en.nthrt(d);
if (rt.pow(d).compareTo(en) == 0) return rt;
}
} catch (NotIntegerException e) {
}
switch (d) {
case 2:
return new Sqrt(a).selfSimplify();
case 3:
case 4:
case 6:
if (a.compareTo(JsclInteger.valueOf(-1)) == 0) return root_minus_1(d);
}
} catch (NotRootException e) {
Generic n[] = Fraction.separateCoefficient(parameters[1]);
if (n[0].compareTo(ONE) == 0 && n[1].compareTo(ONE) == 0) {
// do nothing
} else {
return new Pow(
new Pow(
new Pow(
parameters[0],
n[2]
).selfSimplify(),
new Inverse(
n[1]
).selfSimplify()
).selfSimplify(),
n[0]
).selfSimplify();
}
}
return expressionValue();
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).pow((NumericWrapper) parameters[1]);
}
public String toString() {
StringBuffer buffer = new StringBuffer();
try {
JsclInteger en = parameters[0].integerValue();
if (en.signum() < 0) buffer.append(GenericVariable.valueOf(en, true));
else buffer.append(en);
} catch (NotIntegerException e) {
try {
Variable v = parameters[0].variableValue();
if (v instanceof Fraction || v instanceof Pow) {
buffer.append(GenericVariable.valueOf(parameters[0]));
} else buffer.append(v);
} catch (NotVariableException e2) {
try {
Power o = parameters[0].powerValue();
if (o.exponent() == 1) buffer.append(o.value(true));
else buffer.append(GenericVariable.valueOf(parameters[0]));
} catch (NotPowerException e3) {
buffer.append(GenericVariable.valueOf(parameters[0]));
}
}
}
buffer.append("^");
try {
JsclInteger en = parameters[1].integerValue();
buffer.append(en);
} catch (NotIntegerException e) {
try {
Variable v = parameters[1].variableValue();
if (v instanceof Fraction) {
buffer.append(GenericVariable.valueOf(parameters[1]));
} else buffer.append(v);
} catch (NotVariableException e2) {
try {
parameters[1].powerValue();
buffer.append(parameters[1]);
} catch (NotPowerException e3) {
buffer.append(GenericVariable.valueOf(parameters[1]));
}
}
}
return buffer.toString();
}
public String toJava() {
StringBuffer buffer = new StringBuffer();
buffer.append(parameters[0].toJava());
buffer.append(".pow(");
buffer.append(parameters[1].toJava());
buffer.append(")");
return buffer.toString();
}
void bodyToMathML(MathML element, boolean fenced) {
if (fenced) {
MathML e1 = element.element("mfenced");
bodyToMathML(e1);
element.appendChild(e1);
} else {
bodyToMathML(element);
}
}
void bodyToMathML(MathML element) {
MathML e1 = element.element("msup");
try {
Variable v = parameters[0].variableValue();
if (v instanceof Fraction || v instanceof Pow || v instanceof Exp) {
GenericVariable.valueOf(parameters[0]).toMathML(e1, null);
} else parameters[0].toMathML(e1, null);
} catch (NotVariableException e2) {
try {
Power o = parameters[0].powerValue();
if (o.exponent() == 1) o.value(true).toMathML(e1, null);
else GenericVariable.valueOf(parameters[0]).toMathML(e1, null);
} catch (NotPowerException e3) {
GenericVariable.valueOf(parameters[0]).toMathML(e1, null);
}
}
parameters[1].toMathML(e1, null);
element.appendChild(e1);
}
@Nonnull
public Variable newInstance() {
return new Pow(null, null);
}
}

View File

@ -0,0 +1,30 @@
package jscl.math.function;
import jscl.AngleUnit;
import jscl.math.Generic;
import jscl.math.Variable;
import javax.annotation.Nonnull;
/**
* User: serso
* Date: 11/14/11
* Time: 1:40 PM
*/
public class Rad extends AbstractDms {
public Rad(Generic degrees, Generic minutes, Generic seconds) {
super("rad", degrees, minutes, seconds);
}
@Override
public Generic selfNumeric() {
return AngleUnit.deg.transform(AngleUnit.rad, super.selfNumeric());
}
@Nonnull
@Override
public Variable newInstance() {
return new Rad(null, null, null);
}
}

View File

@ -0,0 +1,419 @@
package jscl.math.function;
import jscl.math.*;
import jscl.math.polynomial.Polynomial;
import jscl.math.polynomial.UnivariatePolynomial;
import jscl.mathml.MathML;
import jscl.util.ArrayComparator;
import javax.annotation.Nonnull;
public class Root extends Algebraic {
protected Generic subscript;
public Root(Generic parameters[], Generic subscript) {
super("root", parameters);
this.subscript = subscript;
}
public Root(Generic parameters[], int s) {
this(parameters, JsclInteger.valueOf(s));
}
public Root(@Nonnull UnivariatePolynomial polynomial, int s) {
this(polynomial.normalize().elements(), s);
}
static Generic nth(Generic parameter[]) {
int degree = parameter.length - 1;
Generic a = new Fraction(parameter[0], parameter[degree]).selfSimplify();
return new Pow(
a.negate(),
new Inverse(JsclInteger.valueOf(degree)).selfSimplify()
).selfSimplify();
}
static Generic linear(Generic parameter[]) {
Generic a = new Fraction(parameter[0], parameter[1]).selfSimplify();
return a.negate();
}
static Generic quadratic(Generic parameter[], int subscript) {
Generic a = new Fraction(parameter[1], parameter[2]).selfSimplify();
Generic b = new Fraction(parameter[0], parameter[2]).selfSimplify();
Generic y = new Sqrt(
a.pow(2).subtract(JsclInteger.valueOf(4).multiply(b))
).selfSimplify();
switch (subscript) {
case 0:
return new Fraction(
a.subtract(y),
JsclInteger.valueOf(2)
).selfSimplify().negate();
default:
return new Fraction(
a.add(y),
JsclInteger.valueOf(2)
).selfSimplify().negate();
}
}
static Generic cubic(Generic parameter[], int subscript) {
Generic a = new Fraction(parameter[2], parameter[3]).selfSimplify();
Generic b = new Fraction(parameter[1], parameter[3]).selfSimplify();
Generic c = new Fraction(parameter[0], parameter[3]).selfSimplify();
Generic y[] = new Generic[2];
for (int i = 0; i < y.length; i++) {
y[i] = new Cubic(
new Root(
new Generic[]{
a.pow(6).subtract(JsclInteger.valueOf(9).multiply(a.pow(4)).multiply(b)).add(JsclInteger.valueOf(27).multiply(a.pow(2)).multiply(b.pow(2))).subtract(JsclInteger.valueOf(27).multiply(b.pow(3))),
JsclInteger.valueOf(2).multiply(a.pow(3)).subtract(JsclInteger.valueOf(9).multiply(a).multiply(b)).add(JsclInteger.valueOf(27).multiply(c)),
JsclInteger.valueOf(1)
},
i
).selfSimplify()
).selfSimplify();
}
switch (subscript) {
case 0:
return new Fraction(
a.subtract(y[0]).subtract(y[1]),
JsclInteger.valueOf(3)
).selfSimplify().negate();
case 1:
return new Fraction(
a.subtract(Constants.Generic.J.multiply(y[0])).subtract(Constants.Generic.J_BAR.multiply(y[1])),
JsclInteger.valueOf(3)
).selfSimplify().negate();
default:
return new Fraction(
a.subtract(Constants.Generic.J_BAR.multiply(y[0])).subtract(Constants.Generic.J.multiply(y[1])),
JsclInteger.valueOf(3)
).selfSimplify().negate();
}
}
static Generic quartic(Generic parameter[], int subscript) {
Generic a = new Fraction(parameter[3], parameter[4]).selfSimplify();
Generic b = new Fraction(parameter[2], parameter[4]).selfSimplify();
Generic c = new Fraction(parameter[1], parameter[4]).selfSimplify();
Generic d = new Fraction(parameter[0], parameter[4]).selfSimplify();
Generic y[] = new Generic[3];
for (int i = 0; i < y.length; i++) {
y[i] = new Sqrt(
new Root(
new Generic[]{
a.pow(6).subtract(JsclInteger.valueOf(8).multiply(a.pow(4)).multiply(b)).add(JsclInteger.valueOf(16).multiply(a.pow(2)).multiply(b.pow(2))).add(JsclInteger.valueOf(16).multiply(a.pow(3)).multiply(c)).subtract(JsclInteger.valueOf(64).multiply(a).multiply(b).multiply(c)).add(JsclInteger.valueOf(64).multiply(c.pow(2))),
JsclInteger.valueOf(-3).multiply(a.pow(4)).add(JsclInteger.valueOf(16).multiply(a.pow(2)).multiply(b)).subtract(JsclInteger.valueOf(16).multiply(b.pow(2))).subtract(JsclInteger.valueOf(16).multiply(a).multiply(c)).add(JsclInteger.valueOf(64).multiply(d)),
JsclInteger.valueOf(3).multiply(a.pow(2)).subtract(JsclInteger.valueOf(8).multiply(b)),
JsclInteger.valueOf(-1)
},
i
).selfSimplify()
).selfSimplify();
}
switch (subscript) {
case 0:
return new Fraction(
a.add(y[0]).subtract(y[1]).subtract(y[2]),
JsclInteger.valueOf(4)
).selfSimplify().negate();
case 1:
return new Fraction(
a.subtract(y[0]).subtract(y[1]).add(y[2]),
JsclInteger.valueOf(4)
).selfSimplify().negate();
case 2:
return new Fraction(
a.add(y[0]).add(y[1]).add(y[2]),
JsclInteger.valueOf(4)
).selfSimplify().negate();
default:
return new Fraction(
a.subtract(y[0]).add(y[1]).subtract(y[2]),
JsclInteger.valueOf(4)
).selfSimplify().negate();
}
}
public static Generic sigma(Generic parameter[], int n) {
Sigma s = new Sigma(parameter, n);
s.compute();
return s.getValue();
}
@Override
public int getMaxParameters() {
return Integer.MAX_VALUE;
}
public Generic subscript() {
return subscript;
}
public Root rootValue() {
return this;
}
public Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException {
boolean polynomial = true;
for (Generic parameter : parameters) {
polynomial = parameter.isPolynomial(variable);
if (!polynomial) {
break;
}
}
if (polynomial) {
return AntiDerivative.compute(this, variable);
} else {
throw new NotIntegrableException(this);
}
}
@Nonnull
public Generic derivative(@Nonnull Variable variable) {
if (compareTo(variable) == 0) {
return JsclInteger.valueOf(1);
} else {
Variable t = new TechnicalVariable("t");
Generic a[] = new Generic[parameters.length];
for (int i = 0; i < parameters.length; i++) a[i] = parameters[i].derivative(variable);
UnivariatePolynomial fact = (UnivariatePolynomial) Polynomial.factory(this);
UnivariatePolynomial p = fact.valueof(parameters);
UnivariatePolynomial q = (UnivariatePolynomial) p.derivative().multiply(t.expressionValue()).add(fact.valueof(a));
UnivariatePolynomial r = (UnivariatePolynomial) Polynomial.factory(t).valueOf(p.resultant(q));
return new Root(r.elements(), subscript).selfExpand();
}
}
public Generic derivative(int n) {
return null;
}
public Generic substitute(@Nonnull Variable variable, @Nonnull Generic generic) {
Root v = (Root) newInstance();
for (int i = 0; i < parameters.length; i++) {
v.parameters[i] = parameters[i].substitute(variable, generic);
}
v.subscript = subscript.substitute(variable, generic);
if (v.isIdentity(variable)) return generic;
else return v.selfExpand();
}
public Generic expand() {
Root v = (Root) newInstance();
for (int i = 0; i < parameters.length; i++) {
v.parameters[i] = parameters[i].expand();
}
v.subscript = subscript.expand();
return v.selfExpand();
}
public Generic factorize() {
Root v = (Root) newInstance();
for (int i = 0; i < parameters.length; i++) {
v.parameters[i] = parameters[i].factorize();
}
v.subscript = subscript;
return v.expressionValue();
}
public Generic elementary() {
Root v = (Root) newInstance();
for (int i = 0; i < parameters.length; i++) {
v.parameters[i] = parameters[i].elementary();
}
v.subscript = subscript.elementary();
return v.selfElementary();
}
public Generic simplify() {
Root v = (Root) newInstance();
for (int i = 0; i < parameters.length; i++) {
v.parameters[i] = parameters[i].simplify();
}
v.subscript = subscript.simplify();
return v.selfSimplify();
}
public Generic numeric() {
Root v = (Root) newInstance();
for (int i = 0; i < parameters.length; i++) {
v.parameters[i] = parameters[i].numeric();
}
v.subscript = subscript;
return v.selfNumeric();
}
public Generic selfExpand() {
if (isZero()) return JsclInteger.valueOf(0);
try {
int s = subscript.integerValue().intValue();
switch (degree()) {
case 1:
return new Fraction(parameters[0], parameters[1]).selfExpand().negate();
}
} catch (NotIntegerException e) {
}
return expressionValue();
}
public Generic selfElementary() {
return selfExpand();
}
public Generic selfSimplify() {
if (isZero()) return JsclInteger.valueOf(0);
try {
int s = subscript.integerValue().intValue();
switch (degree()) {
case 1:
return linear(parameters);
case 2:
return quadratic(parameters, s);
case 3:
return cubic(parameters, s);
case 4:
return quartic(parameters, s);
default:
if (isNth() && s == 0) return nth(parameters);
}
} catch (NotIntegerException e) {
}
return expressionValue();
}
boolean isZero() {
boolean b = degree() > 0;
for (int i = 0; i < degree(); i++) b = b && parameters[i].signum() == 0;
b = b && parameters[degree()].signum() != 0;
return b;
}
boolean isNth() {
boolean b = degree() > 0;
for (int i = 1; i < degree(); i++) b = b && parameters[i].signum() == 0;
b = b && parameters[degree()].signum() != 0;
return b;
}
public int degree() {
return parameters.length - 1;
}
public Generic selfNumeric() {
return NumericWrapper.root(subscript.integerValue().intValue(), parameters);
}
public int compareTo(Variable that) {
if (this == that) return 0;
int c = comparator.compare(this, that);
if (c < 0) return -1;
else if (c > 0) return 1;
else {
Root v = (Root) that;
c = ArrayComparator.comparator.compare(parameters, v.parameters);
if (c < 0) return -1;
else if (c > 0) return 1;
else return subscript.compareTo(v.subscript);
}
}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append(name);
buffer.append("[").append(subscript).append("]");
buffer.append("(");
for (int i = 0; i < parameters.length; i++) {
buffer.append(parameters[i]).append(i < parameters.length - 1 ? ", " : "");
}
buffer.append(")");
return buffer.toString();
}
public String toJava() {
StringBuffer buffer = new StringBuffer();
buffer.append("Numeric.").append(name).append("(");
buffer.append(subscript.integerValue().intValue());
buffer.append(", new Numeric[] {");
for (int i = 0; i < parameters.length; i++) {
buffer.append(parameters[i].toJava()).append(i < parameters.length - 1 ? ", " : "");
}
buffer.append("})");
return buffer.toString();
}
public void toMathML(MathML element, Object data) {
MathML e1;
int exponent = data instanceof Integer ? ((Integer) data).intValue() : 1;
if (exponent == 1) {
e1 = element.element("msub");
nameToMathML(e1);
subscript.toMathML(e1, null);
element.appendChild(e1);
} else {
e1 = element.element("msubsup");
nameToMathML(e1);
subscript.toMathML(e1, null);
MathML e2 = element.element("mn");
e2.appendChild(element.text(String.valueOf(exponent)));
e1.appendChild(e2);
element.appendChild(e1);
}
e1 = element.element("mfenced");
for (int i = 0; i < parameters.length; i++) {
parameters[i].toMathML(e1, null);
}
element.appendChild(e1);
}
void bodyToMathML(MathML element, boolean fenced) {
}
@Nonnull
public Variable newInstance() {
return new Root(new Generic[parameters.length], null);
}
}
class Sigma {
Generic root[];
Generic generic;
boolean place[];
int n;
Sigma(Generic parameter[], int n) {
root = new Generic[parameter.length - 1];
for (int i = 0; i < root.length; i++) root[i] = new Root(parameter, i).expressionValue();
place = new boolean[root.length];
this.n = n;
}
void compute() {
generic = JsclInteger.valueOf(0);
compute(0, n);
}
void compute(int p, int nn) {
if (nn > 0) {
for (int i = p; i < root.length; i++) {
place[i] = true;
compute(i + 1, nn - 1);
place[i] = false;
}
} else {
Generic s = JsclInteger.valueOf(1);
for (int i = 0; i < root.length; i++) {
if (place[i]) s = s.multiply(root[i]);
}
generic = generic.add(s);
}
}
Generic getValue() {
return generic;
}
}

View File

@ -0,0 +1,94 @@
package jscl.math.function;
import jscl.math.*;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class Sgn extends Function {
public Sgn(Generic generic) {
super("sgn", new Generic[]{generic});
}
public Generic antiDerivative(int n) throws NotIntegrableException {
return new Abs(parameters[0]).selfExpand();
}
public Generic derivative(int n) {
return JsclInteger.valueOf(0);
}
public Generic selfExpand() {
final Generic result = selfEvaluate();
if (result == null) {
return expressionValue();
} else {
return result;
}
}
@Nullable
private Generic selfEvaluate() {
Generic result = null;
if (parameters[0].signum() < 0) {
result = new Sgn(parameters[0].negate()).selfExpand().negate();
} else if (parameters[0].signum() == 0) {
result = JsclInteger.valueOf(0);
}
if (result == null) {
try {
result = JsclInteger.valueOf(parameters[0].integerValue().signum());
} catch (NotIntegerException e) {
}
}
return result;
}
public Generic selfElementary() {
return new Fraction(parameters[0], new Abs(parameters[0]).selfElementary()).selfElementary();
}
public Generic selfSimplify() {
final Generic result = selfEvaluate();
if (result == null) {
try {
Variable v = parameters[0].variableValue();
if (v instanceof Abs) {
return JsclInteger.valueOf(1);
} else if (v instanceof Sgn) {
Function f = (Function) v;
return f.selfSimplify();
}
} catch (NotVariableException e) {
}
return expressionValue();
} else {
return result;
}
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).sgn();
}
public String toJava() {
final StringBuilder result = new StringBuilder();
result.append(parameters[0].toJava());
result.append(".sgn()");
return result.toString();
}
@Nonnull
public Variable newInstance() {
return new Sgn(null);
}
}

View File

@ -0,0 +1,179 @@
package jscl.math.function;
import jscl.math.*;
import jscl.mathml.MathML;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class Sqrt extends Algebraic {
public Sqrt(Generic parameter) {
super("", new Generic[]{parameter});
}
public Root rootValue() {
return new Root(new Generic[]{parameters[0].negate(), JsclInteger.valueOf(0), JsclInteger.valueOf(1)}, 0);
}
public Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException {
Root r = rootValue();
Generic g[] = r.getParameters();
if (g[0].isPolynomial(variable)) {
return AntiDerivative.compute(r, variable);
} else {
throw new NotIntegrableException(this);
}
}
public Generic derivative(int n) {
return Constants.Generic.HALF.multiply(new Inverse(selfExpand()).selfExpand());
}
public boolean imaginary() {
return parameters[0] != null && parameters[0].compareTo(JsclInteger.valueOf(-1)) == 0;
}
public Generic selfExpand() {
Generic result;
try {
final JsclInteger p = parameters[0].integerValue();
if (p.signum() < 0) {
// result will be complex => evaluate
result = expressionValue();
} else {
final Generic sqrt = p.sqrt();
if (sqrt.pow(2).compareTo(p) == 0) {
result = sqrt;
} else {
result = expressionValue();
}
}
} catch (NotIntegerException e) {
result = expressionValue();
}
return result;
}
public Generic selfElementary() {
return selfExpand();
}
public Generic selfSimplify() {
Generic result = null;
try {
final JsclInteger p = parameters[0].integerValue();
if (p.signum() < 0) {
return Constants.Generic.I.multiply(new Sqrt(p.negate()).selfSimplify());
} else {
final Generic sqrt = p.sqrt();
if (sqrt.pow(2).compareTo(p) == 0) {
return sqrt;
}
}
result = simplify0(p);
} catch (NotIntegerException e) {
result = simplify0(parameters[0]);
}
if (result == null) {
return expressionValue();
} else {
return result;
}
}
@Nullable
private Generic simplifyFractions() {
final Generic n[] = Fraction.separateCoefficient(parameters[0]);
if (n[0].compareTo(JsclInteger.valueOf(1)) != 0 || n[1].compareTo(JsclInteger.valueOf(1)) != 0) {
// n
final Generic numerator = new Sqrt(n[0]).selfSimplify();
// d
final Generic denominator = new Sqrt(n[1]).selfSimplify();
// fraction = n / d
final Generic fraction = new Fraction(numerator, denominator).selfSimplify();
return new Sqrt(n[2]).selfSimplify().multiply(fraction);
}
return null;
}
@Nullable
private Generic simplify0(@Nonnull Generic generic) {
Generic result;
try {
// let's try to present sqrt expression as products
final Generic products[] = generic.factorize().productValue();
result = JsclInteger.valueOf(1);
for (Generic product : products) {
// and try sqrt for each product
final Power power = product.powerValue();
Generic q = power.value(true);
int c = power.exponent();
result = result.multiply(q.pow(c / 2).multiply(new Sqrt(q).expressionValue().pow(c % 2)));
}
} catch (NotPowerException e) {
result = simplifyFractions();
} catch (NotProductException e) {
result = simplifyFractions();
}
return result;
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).sqrt();
}
public String toJava() {
if (parameters[0].compareTo(JsclInteger.valueOf(-1)) == 0) {
return "Complex.valueOf(0, 1)";
} else {
final StringBuilder result = new StringBuilder();
result.append(parameters[0].toJava());
result.append(".").append(name).append("()");
return result.toString();
}
}
@Override
public String toString() {
final Generic parameter = parameters[0];
if (parameter != null) {
try {
if (JsclInteger.ONE.negate().equals(parameter.integerValue())) {
return Constants.I.getName();
} else {
return super.toString();
}
} catch (NotIntegerException e) {
return super.toString();
}
} else {
return super.toString();
}
}
void bodyToMathML(MathML element, boolean fenced) {
if (parameters[0].compareTo(JsclInteger.valueOf(-1)) == 0) {
MathML e1 = element.element("mi");
e1.appendChild(element.text(/*"\u2148"*/"i"));
element.appendChild(e1);
} else {
MathML e1 = element.element("msqrt");
parameters[0].toMathML(e1, null);
element.appendChild(e1);
}
}
@Nonnull
public Variable newInstance() {
return new Sqrt(null);
}
}

View File

@ -0,0 +1,55 @@
package jscl.math.function;
import jscl.AngleUnit;
import jscl.JsclMathEngine;
import jscl.math.Generic;
import jscl.math.NotIntegrableException;
import jscl.math.Variable;
import jscl.math.polynomial.Polynomial;
import jscl.text.msg.Messages;
import javax.annotation.Nonnull;
public abstract class Trigonometric extends Function {
public Trigonometric(String name, Generic parameter[]) {
super(name, parameter);
}
public Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException {
if (JsclMathEngine.getInstance().getAngleUnits() != AngleUnit.rad) {
throw new NotIntegrableException(Messages.msg_20, getName());
}
final Generic parameter = parameters[0];
if (parameter.isPolynomial(variable)) {
final Polynomial polynomial = Polynomial.factory(variable).valueOf(parameter);
if (polynomial.degree() == 1) {
final Generic elements[] = polynomial.elements();
return new Inverse(elements[1]).selfExpand().multiply(antiDerivative(0));
} else {
throw new NotIntegrableException(this);
}
} else {
throw new NotIntegrableException(this);
}
}
public Generic identity() {
// Generic a[]=parameter[0].sumValue();
// if(a.length>1) {
// Generic s=JsclInteger.valueOf(0);
// for(int i=1;i<a.length;i++) s=s.add(a[i]);
// return identity(a[0],s);
// }
// Generic n[]=Frac.separateCoefficient(parameter[0]);
// if(n[0].compareTo(JsclInteger.valueOf(1))==0);
// else {
// Generic s=new Frac(n[2],n[1]).evaluateSimplify();
// return identity(s,n[0].subtract(JsclInteger.valueOf(1)).multiply(s));
// }
return expressionValue();
}
public abstract Generic identity(Generic a, Generic b);
}

View File

@ -0,0 +1,54 @@
package jscl.math.function.hyperbolic;
import jscl.math.Generic;
import jscl.math.JsclInteger;
import jscl.math.NumericWrapper;
import jscl.math.Variable;
import jscl.math.function.*;
import javax.annotation.Nonnull;
public class Acosh extends ArcTrigonometric {
public Acosh(Generic generic) {
super("acosh", new Generic[]{generic});
}
public Generic derivative(int n) {
return new Inverse(
new Sqrt(
parameters[0].pow(2).subtract(
JsclInteger.valueOf(1)
)
).selfExpand()
).selfExpand();
}
public Generic selfExpand() {
if (parameters[0].signum() == 0) {
return JsclInteger.valueOf(0);
}
return expressionValue();
}
public Generic selfElementary() {
return new Ln(
new Root(
new Generic[]{
JsclInteger.valueOf(-1),
JsclInteger.valueOf(2).multiply(parameters[0]),
JsclInteger.valueOf(-1)
},
0
).selfElementary()
).selfElementary();
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).acosh();
}
@Nonnull
public Variable newInstance() {
return new Acosh(null);
}
}

View File

@ -0,0 +1,55 @@
package jscl.math.function.hyperbolic;
import jscl.math.Generic;
import jscl.math.JsclInteger;
import jscl.math.NumericWrapper;
import jscl.math.Variable;
import jscl.math.function.ArcTrigonometric;
import jscl.math.function.Inverse;
import jscl.math.function.Ln;
import jscl.math.function.Root;
import javax.annotation.Nonnull;
public class Acoth extends ArcTrigonometric {
public Acoth(Generic generic) {
super("acoth", new Generic[]{generic});
}
public Generic derivative(int n) {
return new Inverse(
JsclInteger.valueOf(1).subtract(
parameters[0].pow(2)
)
).selfExpand();
}
public Generic selfExpand() {
if (parameters[0].signum() < 0) {
return new Acoth(parameters[0].negate()).selfExpand().negate();
}
return expressionValue();
}
public Generic selfElementary() {
return new Ln(
new Root(
new Generic[]{
JsclInteger.valueOf(1).add(parameters[0]),
JsclInteger.valueOf(0),
JsclInteger.valueOf(1).subtract(parameters[0])
},
0
).selfElementary()
).selfElementary();
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).acoth();
}
@Nonnull
public Variable newInstance() {
return new Acoth(null);
}
}

View File

@ -0,0 +1,56 @@
package jscl.math.function.hyperbolic;
import jscl.math.Generic;
import jscl.math.JsclInteger;
import jscl.math.NumericWrapper;
import jscl.math.Variable;
import jscl.math.function.*;
import javax.annotation.Nonnull;
public class Asinh extends ArcTrigonometric {
public Asinh(Generic generic) {
super("asinh", new Generic[]{generic});
}
public Generic derivative(int n) {
return new Inverse(
new Sqrt(
JsclInteger.valueOf(1).add(
parameters[0].pow(2)
)
).selfExpand()
).selfExpand();
}
public Generic selfExpand() {
if (parameters[0].signum() < 0) {
return new Asinh(parameters[0].negate()).selfExpand().negate();
} else if (parameters[0].signum() == 0) {
return JsclInteger.valueOf(0);
}
return expressionValue();
}
public Generic selfElementary() {
return new Ln(
new Root(
new Generic[]{
JsclInteger.valueOf(1),
JsclInteger.valueOf(2).multiply(parameters[0]),
JsclInteger.valueOf(-1)
},
0
).selfElementary()
).selfElementary();
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).asinh();
}
@Nonnull
public Variable newInstance() {
return new Asinh(null);
}
}

View File

@ -0,0 +1,57 @@
package jscl.math.function.hyperbolic;
import jscl.math.Generic;
import jscl.math.JsclInteger;
import jscl.math.NumericWrapper;
import jscl.math.Variable;
import jscl.math.function.ArcTrigonometric;
import jscl.math.function.Inverse;
import jscl.math.function.Ln;
import jscl.math.function.Root;
import javax.annotation.Nonnull;
public class Atanh extends ArcTrigonometric {
public Atanh(Generic generic) {
super("atanh", new Generic[]{generic});
}
public Generic derivative(int n) {
return new Inverse(
JsclInteger.valueOf(1).subtract(
parameters[0].pow(2)
)
).selfExpand();
}
public Generic selfExpand() {
if (parameters[0].signum() < 0) {
return new Atanh(parameters[0].negate()).selfExpand().negate();
} else if (parameters[0].signum() == 0) {
return JsclInteger.valueOf(0);
}
return expressionValue();
}
public Generic selfElementary() {
return new Ln(
new Root(
new Generic[]{
JsclInteger.valueOf(1).add(parameters[0]),
JsclInteger.valueOf(0),
JsclInteger.valueOf(-1).add(parameters[0])
},
0
).selfElementary()
).selfElementary();
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).atanh();
}
@Nonnull
public Variable newInstance() {
return new Atanh(null);
}
}

View File

@ -0,0 +1,77 @@
package jscl.math.function.hyperbolic;
import jscl.math.*;
import jscl.math.function.Constants;
import jscl.math.function.Exp;
import jscl.math.function.Trigonometric;
import javax.annotation.Nonnull;
public class Cosh extends Trigonometric {
public Cosh(Generic generic) {
super("cosh", new Generic[]{generic});
}
public Generic antiDerivative(int n) throws NotIntegrableException {
return new Sinh(parameters[0]).selfExpand();
}
public Generic derivative(int n) {
return new Sinh(parameters[0]).selfExpand();
}
public Generic selfExpand() {
if (parameters[0].signum() < 0) {
return new Cosh(parameters[0].negate()).selfExpand();
} else if (parameters[0].signum() == 0) {
return JsclInteger.valueOf(1);
}
return expressionValue();
}
public Generic selfElementary() {
return new Exp(
parameters[0]
).selfElementary().add(
new Exp(
parameters[0].negate()
).selfElementary()
).multiply(Constants.Generic.HALF);
}
public Generic selfSimplify() {
if (parameters[0].signum() < 0) {
return new Cosh(parameters[0].negate()).selfExpand();
} else if (parameters[0].signum() == 0) {
return JsclInteger.valueOf(1);
}
try {
Variable v = parameters[0].variableValue();
if (v instanceof Acosh) {
Generic g[] = ((Acosh) v).getParameters();
return g[0];
}
} catch (NotVariableException e) {
}
return identity();
}
public Generic identity(Generic a, Generic b) {
return new Cosh(a).selfSimplify().multiply(
new Cosh(b).selfSimplify()
).add(
new Sinh(a).selfSimplify().multiply(
new Sinh(b).selfSimplify()
)
);
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).cosh();
}
@Nonnull
public Variable newInstance() {
return new Cosh(null);
}
}

View File

@ -0,0 +1,75 @@
package jscl.math.function.hyperbolic;
import jscl.math.*;
import jscl.math.function.Fraction;
import jscl.math.function.Ln;
import jscl.math.function.Trigonometric;
import javax.annotation.Nonnull;
public class Coth extends Trigonometric {
public Coth(Generic generic) {
super("coth", new Generic[]{generic});
}
public Generic antiDerivative(int n) throws NotIntegrableException {
return new Ln(
JsclInteger.valueOf(4).multiply(
new Sinh(parameters[0]).selfExpand()
)
).selfExpand();
}
public Generic derivative(int n) {
return JsclInteger.valueOf(1).subtract(
new Coth(parameters[0]).selfExpand().pow(2)
);
}
public Generic selfExpand() {
if (parameters[0].signum() < 0) {
return new Coth(parameters[0].negate()).selfExpand().negate();
}
return expressionValue();
}
public Generic selfElementary() {
return new Fraction(
new Cosh(parameters[0]).selfElementary(),
new Sinh(parameters[0]).selfElementary()
).selfElementary();
}
public Generic selfSimplify() {
if (parameters[0].signum() < 0) {
return new Coth(parameters[0].negate()).selfExpand().negate();
}
try {
Variable v = parameters[0].variableValue();
if (v instanceof Acoth) {
Generic g[] = ((Acoth) v).getParameters();
return g[0];
}
} catch (NotVariableException e) {
}
return identity();
}
public Generic identity(Generic a, Generic b) {
Generic ta = new Coth(a).selfSimplify();
Generic tb = new Coth(b).selfSimplify();
return new Fraction(
ta.multiply(tb).add(JsclInteger.valueOf(1)),
ta.add(tb)
).selfSimplify();
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).coth();
}
@Nonnull
public Variable newInstance() {
return new Coth(null);
}
}

View File

@ -0,0 +1,77 @@
package jscl.math.function.hyperbolic;
import jscl.math.*;
import jscl.math.function.Constants;
import jscl.math.function.Exp;
import jscl.math.function.Trigonometric;
import javax.annotation.Nonnull;
public class Sinh extends Trigonometric {
public Sinh(Generic generic) {
super("sinh", new Generic[]{generic});
}
public Generic antiDerivative(int n) throws NotIntegrableException {
return new Cosh(parameters[0]).selfExpand();
}
public Generic derivative(int n) {
return new Cosh(parameters[0]).selfExpand();
}
public Generic selfExpand() {
if (parameters[0].signum() < 0) {
return new Sinh(parameters[0].negate()).selfExpand().negate();
} else if (parameters[0].signum() == 0) {
return JsclInteger.valueOf(0);
}
return expressionValue();
}
public Generic selfElementary() {
return new Exp(
parameters[0]
).selfElementary().subtract(
new Exp(
parameters[0].negate()
).selfElementary()
).multiply(Constants.Generic.HALF);
}
public Generic selfSimplify() {
if (parameters[0].signum() < 0) {
return new Sinh(parameters[0].negate()).selfExpand().negate();
} else if (parameters[0].signum() == 0) {
return JsclInteger.valueOf(0);
}
try {
Variable v = parameters[0].variableValue();
if (v instanceof Asinh) {
Generic g[] = ((Asinh) v).getParameters();
return g[0];
}
} catch (NotVariableException e) {
}
return identity();
}
public Generic identity(Generic a, Generic b) {
return new Cosh(b).selfSimplify().multiply(
new Sinh(a).selfSimplify()
).add(
new Cosh(a).selfSimplify().multiply(
new Sinh(b).selfSimplify()
)
);
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).sinh();
}
@Nonnull
public Variable newInstance() {
return new Sinh(null);
}
}

View File

@ -0,0 +1,81 @@
package jscl.math.function.hyperbolic;
import jscl.math.*;
import jscl.math.function.Fraction;
import jscl.math.function.Ln;
import jscl.math.function.Trigonometric;
import javax.annotation.Nonnull;
public class Tanh extends Trigonometric {
public Tanh(Generic generic) {
super("tanh", new Generic[]{generic});
}
public Generic antiDerivative(int n) throws NotIntegrableException {
return new Ln(
JsclInteger.valueOf(4).multiply(
new Cosh(parameters[0]).selfExpand()
)
).selfExpand();
}
public Generic derivative(int n) {
return JsclInteger.valueOf(1).subtract(
new Tanh(parameters[0]).selfExpand().pow(2)
);
}
public Generic selfExpand() {
if (parameters[0].signum() < 0) {
return new Tanh(parameters[0].negate()).selfExpand().negate();
} else if (parameters[0].signum() == 0) {
return JsclInteger.valueOf(0);
}
return expressionValue();
}
public Generic selfElementary() {
return new Fraction(
new Sinh(parameters[0]).selfElementary(),
new Cosh(parameters[0]).selfElementary()
).selfElementary();
}
public Generic selfSimplify() {
if (parameters[0].signum() < 0) {
return new Tanh(parameters[0].negate()).selfExpand().negate();
} else if (parameters[0].signum() == 0) {
return JsclInteger.valueOf(0);
}
try {
Variable v = parameters[0].variableValue();
if (v instanceof Atanh) {
Generic g[] = ((Atanh) v).getParameters();
return g[0];
}
} catch (NotVariableException e) {
}
return identity();
}
public Generic identity(Generic a, Generic b) {
Generic ta = new Tanh(a).selfSimplify();
Generic tb = new Tanh(b).selfSimplify();
return new Fraction(
ta.add(tb),
JsclInteger.valueOf(1).add(
ta.multiply(tb)
)
).selfSimplify();
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).tanh();
}
@Nonnull
public Variable newInstance() {
return new Tanh(null);
}
}

View File

@ -0,0 +1,54 @@
package jscl.math.function.trigonometric;
import jscl.math.Generic;
import jscl.math.JsclInteger;
import jscl.math.NumericWrapper;
import jscl.math.Variable;
import jscl.math.function.*;
import javax.annotation.Nonnull;
public class Acos extends ArcTrigonometric {
public Acos(Generic generic) {
super("acos", new Generic[]{generic});
}
public Generic derivative(int n) {
return new Inverse(new Sqrt(JsclInteger.valueOf(1).subtract(parameters[0].pow(2))).selfExpand()).selfExpand().negate();
}
public Generic selfExpand() {
if (parameters[0].signum() < 0) {
return Constants.Generic.PI.subtract(new Acos(parameters[0].negate()).selfExpand());
} else if (parameters[0].compareTo(JsclInteger.valueOf(1)) == 0) {
return JsclInteger.valueOf(0);
}
return expressionValue();
}
public Generic selfElementary() {
return Constants.Generic.I.multiply(
new Ln(
new Root(
new Generic[]{
JsclInteger.valueOf(-1),
JsclInteger.valueOf(2).multiply(parameters[0]),
JsclInteger.valueOf(-1)
},
0
).selfElementary()
).selfElementary()
);
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).acos();
}
@Nonnull
public Variable newInstance() {
return new Acos(null);
}
}

View File

@ -0,0 +1,53 @@
package jscl.math.function.trigonometric;
import jscl.math.Generic;
import jscl.math.JsclInteger;
import jscl.math.NumericWrapper;
import jscl.math.Variable;
import jscl.math.function.*;
import javax.annotation.Nonnull;
public class Acot extends ArcTrigonometric {
public Acot(Generic generic) {
super("acot", new Generic[]{generic});
}
public Generic derivative(int n) {
return new Inverse(
JsclInteger.valueOf(1).add(parameters[0].pow(2))
).selfExpand().negate();
}
public Generic selfExpand() {
if (parameters[0].signum() < 0) {
return Constants.Generic.PI.subtract(new Acot(parameters[0].negate()).selfExpand());
}
return expressionValue();
}
public Generic selfElementary() {
return Constants.Generic.I.multiply(
new Ln(
new Root(
new Generic[]{
Constants.Generic.I.add(parameters[0]),
JsclInteger.valueOf(0),
Constants.Generic.I.subtract(parameters[0])
},
0
).selfElementary()
).selfElementary()
);
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).acot();
}
@Nonnull
public Variable newInstance() {
return new Acot(null);
}
}

View File

@ -0,0 +1,57 @@
package jscl.math.function.trigonometric;
import jscl.math.Generic;
import jscl.math.JsclInteger;
import jscl.math.NumericWrapper;
import jscl.math.Variable;
import jscl.math.function.*;
import javax.annotation.Nonnull;
public class Asin extends ArcTrigonometric {
public Asin(Generic generic) {
super("asin", new Generic[]{generic});
}
public Generic derivative(int n) {
return new Inverse(
new Sqrt(
JsclInteger.valueOf(1).subtract(parameters[0].pow(2))
).selfExpand()
).selfExpand();
}
public Generic selfExpand() {
if (parameters[0].signum() < 0) {
return new Asin(parameters[0].negate()).selfExpand().negate();
} else if (parameters[0].signum() == 0) {
return JsclInteger.valueOf(0);
}
return expressionValue();
}
public Generic selfElementary() {
return Constants.Generic.I.multiply(
new Ln(
new Root(
new Generic[]{
JsclInteger.valueOf(-1),
JsclInteger.valueOf(2).multiply(Constants.Generic.I.multiply(parameters[0])),
JsclInteger.valueOf(1)
},
0
).selfElementary()
).selfElementary()
);
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).asin();
}
@Nonnull
public Variable newInstance() {
return new Asin(null);
}
}

View File

@ -0,0 +1,54 @@
package jscl.math.function.trigonometric;
import jscl.math.Generic;
import jscl.math.JsclInteger;
import jscl.math.NumericWrapper;
import jscl.math.Variable;
import jscl.math.function.*;
import javax.annotation.Nonnull;
public class Atan extends ArcTrigonometric {
public Atan(Generic generic) {
super("atan", new Generic[]{generic});
}
public Generic derivative(int n) {
return new Inverse(
JsclInteger.valueOf(1).add(parameters[0].pow(2))
).selfExpand();
}
public Generic selfExpand() {
if (parameters[0].signum() < 0) {
return new Atan(parameters[0].negate()).selfExpand().negate();
} else if (parameters[0].signum() == 0) {
return JsclInteger.valueOf(0);
}
return expressionValue();
}
public Generic selfElementary() {
return Constants.Generic.I.multiply(
new Ln(
new Root(
new Generic[]{
JsclInteger.valueOf(-1).add(Constants.Generic.I.multiply(parameters[0])),
JsclInteger.valueOf(0),
JsclInteger.valueOf(1).add(Constants.Generic.I.multiply(parameters[0]))
},
0
).selfElementary()
).selfElementary()
);
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).atan();
}
@Nonnull
public Variable newInstance() {
return new Atan(null);
}
}

View File

@ -0,0 +1,96 @@
package jscl.math.function.trigonometric;
import jscl.math.*;
import jscl.math.function.Constants;
import jscl.math.function.Exp;
import jscl.math.function.Trigonometric;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class Cos extends Trigonometric {
public Cos(Generic generic) {
super("cos", new Generic[]{generic});
}
public Generic antiDerivative(int n) throws NotIntegrableException {
return new Sin(parameters[0]).selfExpand();
}
public Generic derivative(int n) {
return new Sin(parameters[0]).selfExpand().negate();
}
public Generic selfExpand() {
final Generic result = trySimplify();
if (result != null) {
return result;
} else {
return expressionValue();
}
}
@Nullable
private Generic trySimplify() {
Generic result = null;
if (parameters[0].signum() < 0) {
result = new Cos(parameters[0].negate()).selfExpand();
} else if (parameters[0].signum() == 0) {
result = JsclInteger.valueOf(1);
} else if (parameters[0].compareTo(Constants.Generic.PI) == 0) {
result = JsclInteger.valueOf(-1);
}
return result;
}
public Generic selfElementary() {
return new Exp(
Constants.Generic.I.multiply(parameters[0])
).selfElementary().add(
new Exp(
Constants.Generic.I.multiply(parameters[0].negate())
).selfElementary()
).multiply(Constants.Generic.HALF);
}
public Generic selfSimplify() {
final Generic result = trySimplify();
if (result != null) {
return result;
} else {
try {
Variable v = parameters[0].variableValue();
if (v instanceof Acos) {
Generic g[] = ((Acos) v).getParameters();
return g[0];
}
} catch (NotVariableException e) {
}
return identity();
}
}
public Generic identity(Generic a, Generic b) {
return new Cos(a).selfSimplify().multiply(
new Cos(b).selfSimplify()
).subtract(
new Sin(a).selfSimplify().multiply(
new Sin(b).selfSimplify()
)
);
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).cos();
}
@Nonnull
public Variable newInstance() {
return new Cos(null);
}
}

View File

@ -0,0 +1,75 @@
package jscl.math.function.trigonometric;
import jscl.math.*;
import jscl.math.function.Fraction;
import jscl.math.function.Ln;
import jscl.math.function.Trigonometric;
import javax.annotation.Nonnull;
public class Cot extends Trigonometric {
public Cot(Generic generic) {
super("cot", new Generic[]{generic});
}
public Generic antiDerivative(int n) throws NotIntegrableException {
return new Ln(
JsclInteger.valueOf(4).multiply(
new Sin(parameters[0]).selfExpand()
)
).selfExpand();
}
public Generic derivative(int n) {
return JsclInteger.valueOf(1).add(
new Cot(parameters[0]).selfExpand().pow(2)
).negate();
}
public Generic selfExpand() {
if (parameters[0].signum() < 0) {
return new Cot(parameters[0].negate()).selfExpand().negate();
}
return expressionValue();
}
public Generic selfElementary() {
return new Fraction(
new Cos(parameters[0]).selfElementary(),
new Sin(parameters[0]).selfElementary()
).selfElementary();
}
public Generic selfSimplify() {
if (parameters[0].signum() < 0) {
return new Cot(parameters[0].negate()).selfExpand().negate();
}
try {
Variable v = parameters[0].variableValue();
if (v instanceof Acot) {
Generic g[] = ((Acot) v).getParameters();
return g[0];
}
} catch (NotVariableException e) {
}
return identity();
}
public Generic identity(Generic a, Generic b) {
Generic ta = new Cot(a).selfSimplify();
Generic tb = new Cot(b).selfSimplify();
return new Fraction(
ta.multiply(tb).subtract(JsclInteger.valueOf(1)),
ta.add(tb)
).selfSimplify();
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).cot();
}
@Nonnull
public Variable newInstance() {
return new Cot(null);
}
}

View File

@ -0,0 +1,94 @@
package jscl.math.function.trigonometric;
import jscl.math.*;
import jscl.math.function.Constants;
import jscl.math.function.Exp;
import jscl.math.function.Trigonometric;
import javax.annotation.Nonnull;
import static jscl.math.function.Constants.Generic.HALF;
import static jscl.math.function.Constants.Generic.I;
public class Sin extends Trigonometric {
public Sin(Generic generic) {
super("sin", new Generic[]{generic});
}
public Generic antiDerivative(int n) throws NotIntegrableException {
return new Cos(parameters[0]).selfExpand().negate();
}
public Generic derivative(int n) {
return new Cos(parameters[0]).selfExpand();
}
public Generic selfExpand() {
final Generic result = trySimplify();
if (result != null) {
return result;
} else {
return expressionValue();
}
}
public Generic selfElementary() {
final Generic power = I.multiply(parameters[0]);
final Generic e = new Exp(power).selfElementary().subtract(new Exp(I.multiply(parameters[0].negate())).selfElementary()).multiply(I.negate().multiply(HALF));
return e;
}
public Generic selfSimplify() {
final Generic result = trySimplify();
if (result != null) {
return result;
} else {
try {
Variable v = parameters[0].variableValue();
if (v instanceof Asin) {
Generic g[] = ((Asin) v).getParameters();
return g[0];
}
} catch (NotVariableException e) {
}
return identity();
}
}
private Generic trySimplify() {
Generic result = null;
if (parameters[0].signum() < 0) {
result = new Sin(parameters[0].negate()).selfExpand().negate();
} else if (parameters[0].signum() == 0) {
result = JsclInteger.valueOf(0);
} else if (parameters[0].compareTo(Constants.Generic.PI) == 0) {
result = JsclInteger.valueOf(0);
}
return result;
}
public Generic identity(Generic a, Generic b) {
return new Cos(b).selfSimplify().multiply(
new Sin(a).selfSimplify()
).add(
new Cos(a).selfSimplify().multiply(
new Sin(b).selfSimplify()
)
);
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).sin();
}
@Nonnull
public Variable newInstance() {
return new Sin(null);
}
}

View File

@ -0,0 +1,103 @@
package jscl.math.function.trigonometric;
import jscl.math.*;
import jscl.math.function.Constants;
import jscl.math.function.Fraction;
import jscl.math.function.Ln;
import jscl.math.function.Trigonometric;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class Tan extends Trigonometric {
public Tan(Generic generic) {
super("tan", new Generic[]{generic});
}
public Generic antiDerivative(int n) throws NotIntegrableException {
return new Ln(
JsclInteger.valueOf(4).multiply(
new Cos(parameters[0]).selfExpand()
)
).selfExpand().negate();
}
public Generic derivative(int n) {
return JsclInteger.valueOf(1).add(
new Tan(parameters[0]).selfExpand().pow(2)
);
}
public Generic selfExpand() {
final Generic result = trySimplify();
if (result != null) {
return result;
} else {
return expressionValue();
}
}
public Generic selfElementary() {
return new Fraction(
new Sin(parameters[0]).selfElementary(),
new Cos(parameters[0]).selfElementary()
).selfElementary();
}
public Generic selfSimplify() {
final Generic result = trySimplify();
if (result != null) {
return result;
} else {
try {
Variable v = parameters[0].variableValue();
if (v instanceof Atan) {
Generic g[] = ((Atan) v).getParameters();
return g[0];
}
} catch (NotVariableException e) {
// ok
}
return identity();
}
}
@Nullable
private Generic trySimplify() {
Generic result = null;
if (parameters[0].signum() < 0) {
result = new Tan(parameters[0].negate()).selfExpand().negate();
} else if (parameters[0].signum() == 0) {
result = JsclInteger.valueOf(0);
} else if (parameters[0].compareTo(Constants.Generic.PI) == 0) {
result = JsclInteger.valueOf(0);
}
return result;
}
public Generic identity(Generic a, Generic b) {
Generic ta = new Tan(a).selfSimplify();
Generic tb = new Tan(b).selfSimplify();
return new Fraction(
ta.add(tb),
JsclInteger.valueOf(1).subtract(
ta.multiply(tb)
)
).selfSimplify();
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).tan();
}
@Nonnull
public Variable newInstance() {
return new Tan(null);
}
}

View File

@ -0,0 +1,260 @@
package jscl.math.numeric;
import jscl.AngleUnit;
import jscl.JsclMathEngine;
import jscl.math.NotDivisibleException;
import jscl.text.msg.JsclMessage;
import jscl.text.msg.Messages;
import org.solovyev.common.msg.MessageType;
import javax.annotation.Nonnull;
public final class Complex extends Numeric {
@Nonnull
public static final Complex I = new Complex(0, 1);
private final double real, imaginary;
private Complex(double real, double imaginary) {
this.real = real;
this.imaginary = imaginary;
}
@Nonnull
public static Complex valueOf(double real, double imaginary) {
if (JsclMathEngine.getInstance().getAngleUnits() != AngleUnit.rad) {
JsclMathEngine.getInstance().getMessageRegistry().addMessage(new JsclMessage(Messages.msg_23, MessageType.warning));
}
if (real == 0d && imaginary == 1d) {
return I;
} else {
return new Complex(real, imaginary);
}
}
public Complex add(Complex complex) {
return valueOf(real + complex.real, imaginary + complex.imaginary);
}
@Nonnull
public Numeric add(@Nonnull Numeric that) {
if (that instanceof Complex) {
return add((Complex) that);
} else if (that instanceof Real) {
return add(valueOf(that));
} else {
return that.valueOf(this).add(that);
}
}
public Complex subtract(Complex complex) {
return valueOf(real - complex.real, imaginary - complex.imaginary);
}
@Nonnull
public Numeric subtract(@Nonnull Numeric that) {
if (that instanceof Complex) {
return subtract((Complex) that);
} else if (that instanceof Real) {
return subtract(valueOf(that));
} else {
return that.valueOf(this).subtract(that);
}
}
public Complex multiply(Complex complex) {
return valueOf(real * complex.real - imaginary * complex.imaginary, real * complex.imaginary + imaginary * complex.real);
}
@Nonnull
public Numeric multiply(@Nonnull Numeric that) {
if (that instanceof Complex) {
return multiply((Complex) that);
} else if (that instanceof Real) {
return multiply(valueOf(that));
} else {
return that.multiply(this);
}
}
public Complex divide(Complex complex) throws ArithmeticException {
return multiply((Complex) complex.inverse());
}
@Nonnull
public Numeric divide(@Nonnull Numeric that) throws NotDivisibleException {
if (that instanceof Complex) {
return divide((Complex) that);
} else if (that instanceof Real) {
return divide(valueOf(that));
} else {
return that.valueOf(this).divide(that);
}
}
@Nonnull
public Numeric negate() {
return valueOf(-real, -imaginary);
}
@Nonnull
@Override
public Numeric abs() {
final Numeric realSquare = new Real(real).pow(2);
final Numeric imaginarySquare = new Real(imaginary).pow(2);
final Numeric sum = realSquare.add(imaginarySquare);
return sum.sqrt();
}
public int signum() {
int result;
if (real > .0) {
result = 1;
} else if (real < .0) {
result = -1;
} else {
result = Real.signum(imaginary);
}
return result;
}
public double magnitude() {
return Math.sqrt(real * real + imaginary * imaginary);
}
public double magnitude2() {
return real * real + imaginary * imaginary;
}
public double angle() {
return Math.atan2(imaginary, real);
}
@Nonnull
public Numeric ln() {
if (signum() == 0) {
return Real.ZERO.ln();
} else {
return valueOf(Math.log(magnitude()), angle());
}
}
@Nonnull
public Numeric lg() {
if (signum() == 0) {
return Real.ZERO.lg();
} else {
return valueOf(Math.log10(magnitude()), angle());
}
}
@Nonnull
public Numeric exp() {
return valueOf(Math.cos(defaultToRad(imaginary)), Math.sin(defaultToRad(imaginary))).multiply(Math.exp(real));
}
@Nonnull
public Numeric inverse() {
return ((Complex) conjugate()).divide(magnitude2());
}
Complex multiply(double d) {
return valueOf(real * d, imaginary * d);
}
Complex divide(double d) {
return valueOf(real / d, imaginary / d);
}
public Numeric conjugate() {
return valueOf(real, -imaginary);
}
public double realPart() {
return real;
}
public double imaginaryPart() {
return imaginary;
}
public int compareTo(Complex that) {
if (imaginary < that.imaginary) {
return -1;
} else if (imaginary > that.imaginary) {
return 1;
} else if (imaginary == that.imaginary) {
if (real < that.real) {
return -1;
} else if (real > that.real) {
return 1;
} else if (real == that.real) {
return 0;
} else throw new ArithmeticException();
} else throw new ArithmeticException();
}
public int compareTo(Numeric that) {
if (that instanceof Complex) {
return compareTo((Complex) that);
} else if (that instanceof Real) {
return compareTo(valueOf(that));
} else {
return that.valueOf(this).compareTo(that);
}
}
public Complex copyOf(@Nonnull Complex complex) {
return valueOf(complex.real, complex.imaginary);
}
@Nonnull
public Numeric valueOf(@Nonnull Numeric numeric) {
if (numeric instanceof Complex) {
return copyOf((Complex) numeric);
} else if (numeric instanceof Real) {
Real d = (Real) numeric;
return d.toComplex();
} else throw new ArithmeticException();
}
public String toString() {
final StringBuilder result = new StringBuilder();
if (imaginary == 0.) {
result.append(toString(real));
} else {
if (real != 0.) {
result.append(toString(real));
if (imaginary > 0.) {
result.append("+");
}
}
if (imaginary != 1.) {
if (imaginary == -1.) {
result.append("-");
} else {
if (imaginary < 0.) {
final String imagStr = toString(imaginary);
// due to rounding we can forget sign (-0.00000000001 can be round to 0 => plus sign would not be added above and no sign will be before i)
if (imagStr.startsWith("-")) {
result.append(imagStr);
} else {
result.append("-").append(imagStr);
}
} else {
result.append(toString(imaginary));
}
result.append("*");
}
}
result.append("i");
}
return result.toString();
}
}

View File

@ -0,0 +1,114 @@
package jscl.math.numeric;
import javax.annotation.Nonnull;
public interface INumeric<T extends INumeric<T>> {
@Nonnull
T pow(int exponent);
@Nonnull
T abs();
@Nonnull
T negate();
int signum();
@Nonnull
T sgn();
@Nonnull
T ln();
@Nonnull
T lg();
@Nonnull
T exp();
@Nonnull
T inverse();
@Nonnull
T sqrt();
@Nonnull
T nThRoot(int n);
/*
* ******************************************************************************************
* <p/>
* TRIGONOMETRIC FUNCTIONS
* <p/>
* *******************************************************************************************/
@Nonnull
T sin();
@Nonnull
T cos();
@Nonnull
T tan();
@Nonnull
T cot();
/*
* ******************************************************************************************
* <p/>
* INVERSE TRIGONOMETRIC FUNCTIONS
* <p/>
* *******************************************************************************************/
@Nonnull
T asin();
@Nonnull
T acos();
@Nonnull
T atan();
@Nonnull
T acot();
/*
* ******************************************************************************************
* <p/>
* HYPERBOLIC TRIGONOMETRIC FUNCTIONS
* <p/>
* *******************************************************************************************/
@Nonnull
T sinh();
@Nonnull
T cosh();
@Nonnull
T tanh();
@Nonnull
T coth();
/*
* ******************************************************************************************
* <p/>
* INVERSE HYPERBOLIC TRIGONOMETRIC FUNCTIONS
* <p/>
* *******************************************************************************************/
@Nonnull
T asinh();
@Nonnull
T acosh();
@Nonnull
T atanh();
@Nonnull
T acoth();
}

View File

@ -0,0 +1,312 @@
package jscl.math.numeric;
import jscl.math.NotDivisibleException;
import jscl.util.ArrayComparator;
import javax.annotation.Nonnull;
public class Matrix extends Numeric {
@Nonnull
private final Numeric m[][];
private final int rows, cols;
public Matrix(@Nonnull Numeric m[][]) {
this.m = m;
rows = m.length;
cols = m.length > 0 ? m[0].length : 0;
}
public static Matrix identity(int dimension) {
return identity(dimension, dimension);
}
public static Matrix identity(int n, int p) {
Matrix m = new Matrix(new Numeric[n][p]);
for (int i = 0; i < n; i++) {
for (int j = 0; j < p; j++) {
if (i == j) {
m.m[i][j] = Real.ONE;
} else {
m.m[i][j] = Real.ZERO;
}
}
}
return m;
}
public Numeric[][] elements() {
return m;
}
public Matrix add(Matrix matrix) {
Matrix m = newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m.m[i][j] = this.m[i][j].add(matrix.m[i][j]);
}
}
return m;
}
@Nonnull
public Numeric add(@Nonnull Numeric that) {
if (that instanceof Matrix) {
return add((Matrix) that);
} else {
return add(valueOf(that));
}
}
public Matrix subtract(Matrix matrix) {
Matrix m = newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m.m[i][j] = this.m[i][j].subtract(matrix.m[i][j]);
}
}
return m;
}
@Nonnull
public Numeric subtract(@Nonnull Numeric that) {
if (that instanceof Matrix) {
return subtract((Matrix) that);
} else {
return subtract(valueOf(that));
}
}
public Matrix multiply(Matrix matrix) {
if (cols != matrix.rows) throw new ArithmeticException();
Matrix m = newInstance(new Numeric[rows][matrix.cols]);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < matrix.cols; j++) {
m.m[i][j] = Real.ZERO;
for (int k = 0; k < cols; k++) {
m.m[i][j] = m.m[i][j].add(this.m[i][k].multiply(matrix.m[k][j]));
}
}
}
return m;
}
@Nonnull
public Numeric multiply(@Nonnull Numeric that) {
if (that instanceof Matrix) {
return multiply((Matrix) that);
} else if (that instanceof Vector) {
Vector v = ((Vector) that).newInstance(new Numeric[rows]);
Vector v2 = (Vector) that;
if (cols != v2.n) throw new ArithmeticException();
for (int i = 0; i < rows; i++) {
v.element[i] = Real.ZERO;
for (int k = 0; k < cols; k++) {
v.element[i] = v.element[i].add(m[i][k].multiply(v2.element[k]));
}
}
return v;
} else {
Matrix m = newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m.m[i][j] = this.m[i][j].multiply(that);
}
}
return m;
}
}
@Nonnull
public Numeric divide(@Nonnull Numeric that) throws NotDivisibleException {
if (that instanceof Matrix) {
return multiply(that.inverse());
} else if (that instanceof Vector) {
throw new ArithmeticException();
} else {
Matrix m = newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m.m[i][j] = this.m[i][j].divide(that);
}
}
return m;
}
}
@Nonnull
public Numeric negate() {
Matrix m = newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m.m[i][j] = this.m[i][j].negate();
}
}
return m;
}
public int signum() {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
int c = m[i][j].signum();
if (c < 0) {
return -1;
} else if (c > 0) {
return 1;
}
}
}
return 0;
}
@Nonnull
public Numeric valueOf(@Nonnull Numeric numeric) {
if (numeric instanceof Matrix || numeric instanceof Vector) {
throw new ArithmeticException();
} else {
Matrix m = (Matrix) identity(rows, cols).multiply(numeric);
return newInstance(m.m);
}
}
public Numeric[] vectors() {
Vector v[] = new Vector[rows];
for (int i = 0; i < rows; i++) {
v[i] = new Vector(new Numeric[cols]);
for (int j = 0; j < cols; j++) {
v[i].element[j] = m[i][j];
}
}
return v;
}
public Numeric transpose() {
Matrix m = newInstance(new Numeric[cols][rows]);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m.m[j][i] = this.m[i][j];
}
}
return m;
}
public Numeric trace() {
Numeric s = Real.ZERO;
for (int i = 0; i < rows; i++) {
s = s.add(m[i][i]);
}
return s;
}
@Nonnull
public Numeric inverse() {
Matrix m = newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < rows; j++) {
m.m[i][j] = inverseElement(i, j);
}
}
return m.transpose().divide(determinant());
}
Numeric inverseElement(int k, int l) {
final Matrix result = newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < rows; j++) {
if (i == k) {
result.m[i][j] = Real.valueOf(j == l ? 1 : 0);
} else {
result.m[i][j] = this.m[i][j];
}
}
}
return result.determinant();
}
public Numeric determinant() {
if (rows > 1) {
Numeric a = Real.ZERO;
for (int i = 0; i < rows; i++) {
if (m[i][0].signum() != 0) {
Matrix m = newInstance(new Numeric[rows - 1][rows - 1]);
for (int j = 0; j < rows - 1; j++) {
for (int k = 0; k < rows - 1; k++) m.m[j][k] = this.m[j < i ? j : j + 1][k + 1];
}
if (i % 2 == 0) {
a = a.add(this.m[i][0].multiply(m.determinant()));
} else {
a = a.subtract(this.m[i][0].multiply(m.determinant()));
}
}
}
return a;
} else if (rows > 0) return m[0][0];
else return Real.ZERO;
}
@Nonnull
public Numeric ln() {
throw new ArithmeticException();
}
@Nonnull
@Override
public Numeric lg() {
throw new ArithmeticException();
}
@Nonnull
public Numeric exp() {
throw new ArithmeticException();
}
public Numeric conjugate() {
Matrix m = newInstance();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m.m[i][j] = this.m[i][j].conjugate();
}
}
return m;
}
public int compareTo(Matrix matrix) {
return ArrayComparator.comparator.compare(vectors(), matrix.vectors());
}
public int compareTo(Numeric numeric) {
if (numeric instanceof Matrix) {
return compareTo((Matrix) numeric);
} else {
return compareTo(valueOf(numeric));
}
}
public String toString() {
final StringBuilder result = new StringBuilder();
result.append("{");
for (int i = 0; i < rows; i++) {
result.append("{");
for (int j = 0; j < cols; j++) {
result.append(m[i][j]).append(j < cols - 1 ? ", " : "");
}
result.append("}").append(i < rows - 1 ? ",\n" : "");
}
result.append("}");
return result.toString();
}
protected Matrix newInstance() {
return newInstance(new Numeric[rows][cols]);
}
protected Matrix newInstance(Numeric element[][]) {
return new Matrix(element);
}
}

View File

@ -0,0 +1,328 @@
package jscl.math.numeric;
import jscl.AngleUnit;
import jscl.JsclMathEngine;
import jscl.math.Arithmetic;
import javax.annotation.Nonnull;
import static jscl.math.numeric.Complex.I;
import static jscl.math.numeric.Real.ONE;
import static jscl.math.numeric.Real.TWO;
public abstract class Numeric implements Arithmetic<Numeric>, INumeric<Numeric>, Comparable {
/*@Nonnull
public Numeric subtract(@Nonnull Numeric numeric) {
return add(numeric.negate());
}*/
public static Numeric root(int subscript, Numeric parameter[]) {
throw new ArithmeticException();
}
protected static double defaultToRad(double value) {
return JsclMathEngine.getInstance().getAngleUnits().transform(AngleUnit.rad, value);
}
protected static double radToDefault(double value) {
return AngleUnit.rad.transform(JsclMathEngine.getInstance().getAngleUnits(), value);
}
@Nonnull
protected static Numeric defaultToRad(@Nonnull Numeric value) {
return JsclMathEngine.getInstance().getAngleUnits().transform(AngleUnit.rad, value);
}
@Nonnull
protected static Numeric radToDefault(@Nonnull Numeric value) {
return AngleUnit.rad.transform(JsclMathEngine.getInstance().getAngleUnits(), value);
}
@Override
@Nonnull
public Numeric abs() {
return signum() < 0 ? negate() : this;
}
@Nonnull
@Override
public Numeric sgn() {
return divide(abs());
}
@Nonnull
@Override
public Numeric inverse() {
return ONE.divide(this);
}
@Override
@Nonnull
public Numeric pow(int exponent) {
Numeric result = ONE;
for (int i = 0; i < exponent; i++) {
result = result.multiply(this);
}
return result;
}
/*
* ******************************************************************************************
* <p/>
* CONVERSION FUNCTIONS (rad to default angle units and vice versa)
* <p/>
* *******************************************************************************************
*/
public Numeric pow(@Nonnull Numeric numeric) {
if (numeric.signum() == 0) {
return ONE;
} else if (numeric.compareTo(ONE) == 0) {
return this;
} else {
return numeric.multiply(this.ln()).exp();
}
}
@Nonnull
@Override
public Numeric sqrt() {
return nThRoot(2);
}
@Nonnull
@Override
public Numeric nThRoot(int n) {
return pow(Real.valueOf(1. / n));
}
public abstract Numeric conjugate();
/*
* ******************************************************************************************
* <p/>
* TRIGONOMETRIC FUNCTIONS
* <p/>
* *******************************************************************************************
*/
@Nonnull
@Override
public Numeric sin() {
// e = exp(i)
final Numeric e = defaultToRad(this).multiply(I).exp();
// e1 = exp(2ix)
final Numeric e1 = e.pow(2);
// result = [i - i * exp(2i)] / [2exp(i)]
return I.subtract(e1.multiply(I)).divide(TWO.multiply(e));
}
@Nonnull
@Override
public Numeric cos() {
// e = exp(ix)
final Numeric e = defaultToRad(this).multiply(I).exp();
// e1 = exp(2ix)
final Numeric e1 = e.pow(2);
// result = [ 1 + exp(2ix) ] / (2 *exp(ix))
return ONE.add(e1).divide(TWO.multiply(e));
}
@Nonnull
@Override
public Numeric tan() {
// e = exp(2xi)
final Numeric e = defaultToRad(this).multiply(I).exp().pow(2);
// e1 = i * exp(2xi)
final Numeric e1 = e.multiply(I);
// result = (i - i * exp(2xi)) / ( 1 + exp(2xi) )
return I.subtract(e1).divide(ONE.add(e));
}
@Nonnull
@Override
public Numeric cot() {
// e = exp(2xi)
final Numeric e = I.multiply(defaultToRad(this)).exp().pow(2);
// result = - (i + i * exp(2ix)) / ( 1 - exp(2xi))
return I.add(I.multiply(e)).divide(ONE.subtract(e)).negate();
}
/**
* ******************************************************************************************
* <p/>
* INVERSE TRIGONOMETRIC FUNCTIONS
* <p/>
* *******************************************************************************************
*/
@Nonnull
@Override
public Numeric asin() {
// e = (1 - x^2)
final Numeric e = ONE.subtract(this.pow(2)).sqrt();
// result = -iln[xi + (1 - x^2)]
return radToDefault(this.multiply(I).add(e).ln().multiply(I.negate()));
}
@Nonnull
@Override
public Numeric acos() {
// e = (-1 + x^2) = i (1 - x^2)
final Numeric e = I.multiply(Real.ONE.subtract(this.pow(2)).sqrt());
// result = -i * ln[ x + (-1 + x^2) ]
return radToDefault(this.add(e).ln().multiply(I.negate()));
}
@Nonnull
@Override
public Numeric atan() {
// e = ln[(i + x)/(i-x)]
final Numeric e = I.add(this).divide(I.subtract(this)).ln();
// result = iln[(i + x)/(i-x)]/2
return radToDefault(I.multiply(e).divide(TWO));
}
@Nonnull
@Override
public Numeric acot() {
// e = ln[-(i + x)/(i-x)]
final Numeric e = I.add(this).divide(I.subtract(this)).negate().ln();
// result = iln[-(i + x)/(i-x)]/2
return radToDefault(I.multiply(e).divide(TWO));
}
/**
* ******************************************************************************************
* <p/>
* HYPERBOLIC TRIGONOMETRIC FUNCTIONS
* <p/>
* *******************************************************************************************
*/
@Nonnull
@Override
public Numeric sinh() {
final Numeric thisRad = defaultToRad(this);
// e = exp(2x)
final Numeric e = thisRad.exp().pow(2);
// e1 = 2exp(x)
final Numeric e1 = TWO.multiply(thisRad.exp());
// result = -[1 - exp(2x)]/[2exp(x)]
return ONE.subtract(e).divide(e1).negate();
}
@Nonnull
@Override
public Numeric cosh() {
final Numeric thisExpRad = defaultToRad(this).exp();
// e = exp(2x)
final Numeric e = thisExpRad.pow(2);
// e1 = 2exp(x)
final Numeric e1 = TWO.multiply(thisExpRad);
// result = [ 1 + exp(2x )] / 2exp(x)
return ONE.add(e).divide(e1);
}
@Nonnull
@Override
public Numeric tanh() {
// e = exp(2x)
final Numeric e = defaultToRad(this).exp().pow(2);
// result = - (1 - exp(2x)) / (1 + exp(2x))
return ONE.subtract(e).divide(ONE.add(e)).negate();
}
@Nonnull
@Override
public Numeric coth() {
// e = exp(2x)
final Numeric e = defaultToRad(this).exp().pow(2);
// result = - (1 + exp(2x)) / (1 - exp(2x))
return ONE.add(e).divide(ONE.subtract(e)).negate();
}
/**
* ******************************************************************************************
* <p/>
* INVERSE HYPERBOLIC TRIGONOMETRIC FUNCTIONS
* <p/>
* *******************************************************************************************
*/
@Nonnull
@Override
public Numeric asinh() {
// e = ( 1 + x ^ 2 )
final Numeric e = ONE.add(this.pow(2)).sqrt();
// result = ln [ x + ( 1 + x ^ 2 ) ]
return radToDefault(this.add(e).ln());
}
@Nonnull
@Override
public Numeric acosh() {
// e = (x ^ 2 - 1)
final Numeric e = Real.valueOf(-1).add(this.pow(2)).sqrt();
// result = ln( x + (x ^ 2 - 1) )
return radToDefault(this.add(e).ln());
}
@Nonnull
@Override
public Numeric atanh() {
// e = 1 - x
final Numeric e = ONE.subtract(this);
// result = ln [ ( 1 + x ) / ( 1 - x ) ] / 2
return radToDefault(ONE.add(this).divide(e).ln().divide(TWO));
}
@Nonnull
@Override
public Numeric acoth() {
// e = 1 - x
final Numeric e = ONE.subtract(this);
// result = ln [ - (1 + x) / (1 - x) ] / 2
return radToDefault(ONE.add(this).divide(e).negate().ln().divide(TWO));
}
@Nonnull
public abstract Numeric valueOf(@Nonnull Numeric numeric);
public abstract int compareTo(Numeric numeric);
public int compareTo(Object o) {
return compareTo((Numeric) o);
}
public boolean equals(Object obj) {
return obj instanceof Numeric && compareTo((Numeric) obj) == 0;
}
@Nonnull
protected String toString(final double value) {
return JsclMathEngine.getInstance().format(value, JsclMathEngine.getInstance().getNumeralBase());
}
}

View File

@ -0,0 +1,280 @@
package jscl.math.numeric;
import jscl.math.NotDivisibleException;
import javax.annotation.Nonnull;
public final class Real extends Numeric {
public static final Real ZERO = new Real(0d);
public static final Real ONE = new Real(1d);
public static final Real TWO = new Real(2d);
private final static Real PI_DIV_BY_2_RAD = Real.valueOf(Math.PI).divide(TWO);
private final static Double PI_DIV_BY_2_RAD_DOUBLE = Math.PI / 2;
private final double content;
Real(double val) {
content = val;
}
public static int signum(double value) {
return value == 0. ? 0 : (value < 0. ? -1 : 1);
}
public static Real valueOf(double value) {
if (value == 0d) {
return ZERO;
} else if (value == 1d) {
return ONE;
} else if (value == 2d) {
return TWO;
} else {
return new Real(value);
}
}
public Real add(@Nonnull Real that) {
return new Real(content + that.content);
}
@Nonnull
public Numeric add(@Nonnull Numeric that) {
if (that instanceof Real) {
return add((Real) that);
} else {
return that.valueOf(this).add(that);
}
}
public Real subtract(Real that) {
return new Real(content - that.content);
}
@Nonnull
public Numeric subtract(@Nonnull Numeric that) {
if (that instanceof Real) {
return subtract((Real) that);
} else {
return that.valueOf(this).subtract(that);
}
}
public Real multiply(Real that) {
return new Real(content * that.content);
}
@Nonnull
public Numeric multiply(@Nonnull Numeric that) {
if (that instanceof Real) {
return multiply((Real) that);
} else {
return that.multiply(this);
}
}
public Real divide(Real that) throws ArithmeticException {
return new Real(content / that.content);
}
@Nonnull
public Numeric divide(@Nonnull Numeric that) throws NotDivisibleException {
if (that instanceof Real) {
return divide((Real) that);
} else {
return that.valueOf(this).divide(that);
}
}
@Nonnull
public Numeric negate() {
return new Real(-content);
}
public int signum() {
return signum(content);
}
@Nonnull
public Numeric ln() {
if (signum() >= 0) {
return new Real(Math.log(content));
} else {
return Complex.valueOf(Math.log(-content), Math.PI);
}
}
@Nonnull
public Numeric lg() {
if (signum() >= 0) {
return new Real(Math.log10(content));
} else {
return Complex.valueOf(Math.log10(-content), Math.PI);
}
}
@Nonnull
public Numeric exp() {
return new Real(Math.exp(content));
}
@Nonnull
public Numeric inverse() {
return new Real(1. / content);
}
public Numeric pow(Real that) {
if (signum() < 0) {
return Complex.valueOf(content, 0).pow(that);
} else {
return new Real(Math.pow(content, that.content));
}
}
public Numeric pow(@Nonnull Numeric numeric) {
if (numeric instanceof Real) {
return pow((Real) numeric);
} else {
return numeric.valueOf(this).pow(numeric);
}
}
@Nonnull
public Numeric sqrt() {
if (signum() < 0) {
return Complex.I.multiply(negate().sqrt());
} else {
return new Real(Math.sqrt(content));
}
}
@Nonnull
public Numeric nThRoot(int n) {
if (signum() < 0) {
return n % 2 == 0 ? sqrt().nThRoot(n / 2) : negate().nThRoot(n).negate();
} else {
return super.nThRoot(n);
}
}
public Numeric conjugate() {
return this;
}
@Nonnull
public Numeric acos() {
final Real result = new Real(radToDefault(Math.acos(content)));
if (Double.isNaN(result.content)) {
return super.acos();
}
return result;
}
@Nonnull
public Numeric asin() {
final Real result = new Real(radToDefault(Math.asin(content)));
if (Double.isNaN(result.content)) {
return super.asin();
}
return result;
}
@Nonnull
public Numeric atan() {
final Real result = new Real(radToDefault(atanRad()));
if (Double.isNaN(result.content)) {
return super.atan();
}
return result;
}
@Nonnull
private Double atanRad() {
return Math.atan(content);
}
@Nonnull
@Override
public Numeric acot() {
final Real result = new Real(radToDefault(PI_DIV_BY_2_RAD_DOUBLE - atanRad()));
if (Double.isNaN(result.content)) {
return super.acot();
}
return result;
}
@Nonnull
public Numeric cos() {
return new Real(Math.cos(defaultToRad(content)));
}
@Nonnull
public Numeric sin() {
return new Real(Math.sin(defaultToRad(content)));
}
@Nonnull
public Numeric tan() {
return new Real(tan(defaultToRad(content)));
}
private double tan(double value) {
if (value > Math.PI || value < Math.PI) {
value = value % Math.PI;
}
if (value == Math.PI / 2) {
return Double.POSITIVE_INFINITY;
}
if (value == Math.PI) {
return 0;
}
if (value == -Math.PI / 2) {
return Double.NEGATIVE_INFINITY;
}
if (value == -Math.PI) {
return 0;
}
return Math.tan(value);
}
@Nonnull
@Override
public Numeric cot() {
return Real.ONE.divide(tan());
}
public Real valueOf(Real value) {
return new Real(value.content);
}
@Nonnull
public Numeric valueOf(@Nonnull Numeric numeric) {
if (numeric instanceof Real) {
return valueOf((Real) numeric);
} else throw new ArithmeticException();
}
public double doubleValue() {
return content;
}
public int compareTo(@Nonnull Real that) {
return Double.compare(this.content, that.content);
}
public int compareTo(Numeric numeric) {
if (numeric instanceof Real) {
return compareTo((Real) numeric);
} else {
return numeric.valueOf(this).compareTo(numeric);
}
}
public String toString() {
return toString(content);
}
@Nonnull
public Complex toComplex() {
return Complex.valueOf(this.content, 0.);
}
}

Some files were not shown because too many files have changed in this diff Show More