JSCL imported to C++
This commit is contained in:
parent
1120864668
commit
e751d2cbd4
@ -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
37
jscl/build.gradle
Normal 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
|
67
jscl/src/main/java/jscl/AbstractJsclArithmeticException.java
Normal file
67
jscl/src/main/java/jscl/AbstractJsclArithmeticException.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
119
jscl/src/main/java/jscl/AngleUnit.java
Normal file
119
jscl/src/main/java/jscl/AngleUnit.java
Normal 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)));
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
345
jscl/src/main/java/jscl/JsclMathEngine.java
Normal file
345
jscl/src/main/java/jscl/JsclMathEngine.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
59
jscl/src/main/java/jscl/MathContext.java
Normal file
59
jscl/src/main/java/jscl/MathContext.java
Normal 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);
|
||||||
|
}
|
36
jscl/src/main/java/jscl/MathEngine.java
Normal file
36
jscl/src/main/java/jscl/MathEngine.java
Normal 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);
|
||||||
|
}
|
10
jscl/src/main/java/jscl/NotSupportedException.java
Normal file
10
jscl/src/main/java/jscl/NotSupportedException.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
170
jscl/src/main/java/jscl/NumeralBase.java
Normal file
170
jscl/src/main/java/jscl/NumeralBase.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
12
jscl/src/main/java/jscl/NumeralBaseException.java
Normal file
12
jscl/src/main/java/jscl/NumeralBaseException.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
232
jscl/src/main/java/jscl/math/AntiDerivative.java
Normal file
232
jscl/src/main/java/jscl/math/AntiDerivative.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
19
jscl/src/main/java/jscl/math/Arithmetic.java
Normal file
19
jscl/src/main/java/jscl/math/Arithmetic.java
Normal 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;
|
||||||
|
|
||||||
|
}
|
110
jscl/src/main/java/jscl/math/Clifford.java
Normal file
110
jscl/src/main/java/jscl/math/Clifford.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
41
jscl/src/main/java/jscl/math/Debug.java
Normal file
41
jscl/src/main/java/jscl/math/Debug.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
49
jscl/src/main/java/jscl/math/DoubleVariable.java
Normal file
49
jscl/src/main/java/jscl/math/DoubleVariable.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
887
jscl/src/main/java/jscl/math/Expression.java
Normal file
887
jscl/src/main/java/jscl/math/Expression.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
60
jscl/src/main/java/jscl/math/ExpressionVariable.java
Normal file
60
jscl/src/main/java/jscl/math/ExpressionVariable.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
298
jscl/src/main/java/jscl/math/Factorization.java
Normal file
298
jscl/src/main/java/jscl/math/Factorization.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
4
jscl/src/main/java/jscl/math/Field.java
Normal file
4
jscl/src/main/java/jscl/math/Field.java
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
package jscl.math;
|
||||||
|
|
||||||
|
public interface Field {
|
||||||
|
}
|
189
jscl/src/main/java/jscl/math/Generic.java
Normal file
189
jscl/src/main/java/jscl/math/Generic.java
Normal 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();
|
||||||
|
}
|
118
jscl/src/main/java/jscl/math/GenericVariable.java
Normal file
118
jscl/src/main/java/jscl/math/GenericVariable.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
60
jscl/src/main/java/jscl/math/IntegerVariable.java
Normal file
60
jscl/src/main/java/jscl/math/IntegerVariable.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
15
jscl/src/main/java/jscl/math/JsclBoolean.java
Normal file
15
jscl/src/main/java/jscl/math/JsclBoolean.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
367
jscl/src/main/java/jscl/math/JsclInteger.java
Normal file
367
jscl/src/main/java/jscl/math/JsclInteger.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
466
jscl/src/main/java/jscl/math/JsclVector.java
Normal file
466
jscl/src/main/java/jscl/math/JsclVector.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
455
jscl/src/main/java/jscl/math/Literal.java
Normal file
455
jscl/src/main/java/jscl/math/Literal.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
544
jscl/src/main/java/jscl/math/Matrix.java
Normal file
544
jscl/src/main/java/jscl/math/Matrix.java
Normal 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]);
|
||||||
|
}
|
||||||
|
}
|
14
jscl/src/main/java/jscl/math/MatrixVariable.java
Normal file
14
jscl/src/main/java/jscl/math/MatrixVariable.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
210
jscl/src/main/java/jscl/math/ModularInteger.java
Normal file
210
jscl/src/main/java/jscl/math/ModularInteger.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
11
jscl/src/main/java/jscl/math/NotDivisibleException.java
Normal file
11
jscl/src/main/java/jscl/math/NotDivisibleException.java
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package jscl.math;
|
||||||
|
|
||||||
|
public class NotDivisibleException extends ArithmeticException {
|
||||||
|
|
||||||
|
public NotDivisibleException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotDivisibleException(String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
}
|
10
jscl/src/main/java/jscl/math/NotExpressionException.java
Normal file
10
jscl/src/main/java/jscl/math/NotExpressionException.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package jscl.math;
|
||||||
|
|
||||||
|
public class NotExpressionException extends ArithmeticException {
|
||||||
|
public NotExpressionException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotExpressionException(String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
}
|
11
jscl/src/main/java/jscl/math/NotIntegerException.java
Normal file
11
jscl/src/main/java/jscl/math/NotIntegerException.java
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package jscl.math;
|
||||||
|
|
||||||
|
public class NotIntegerException extends ArithmeticException {
|
||||||
|
public NotIntegerException() {
|
||||||
|
this("Not integer!");
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotIntegerException(String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
}
|
25
jscl/src/main/java/jscl/math/NotIntegrableException.java
Normal file
25
jscl/src/main/java/jscl/math/NotIntegrableException.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
10
jscl/src/main/java/jscl/math/NotPowerException.java
Normal file
10
jscl/src/main/java/jscl/math/NotPowerException.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package jscl.math;
|
||||||
|
|
||||||
|
public class NotPowerException extends ArithmeticException {
|
||||||
|
public NotPowerException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotPowerException(String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
}
|
10
jscl/src/main/java/jscl/math/NotProductException.java
Normal file
10
jscl/src/main/java/jscl/math/NotProductException.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package jscl.math;
|
||||||
|
|
||||||
|
public class NotProductException extends ArithmeticException {
|
||||||
|
public NotProductException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotProductException(String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
}
|
10
jscl/src/main/java/jscl/math/NotVariableException.java
Normal file
10
jscl/src/main/java/jscl/math/NotVariableException.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package jscl.math;
|
||||||
|
|
||||||
|
public class NotVariableException extends ArithmeticException {
|
||||||
|
public NotVariableException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotVariableException(String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
}
|
445
jscl/src/main/java/jscl/math/NumericWrapper.java
Normal file
445
jscl/src/main/java/jscl/math/NumericWrapper.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
27
jscl/src/main/java/jscl/math/Power.java
Normal file
27
jscl/src/main/java/jscl/math/Power.java
Normal 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 + ")";
|
||||||
|
}
|
||||||
|
}
|
311
jscl/src/main/java/jscl/math/Rational.java
Normal file
311
jscl/src/main/java/jscl/math/Rational.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
266
jscl/src/main/java/jscl/math/Simplification.java
Normal file
266
jscl/src/main/java/jscl/math/Simplification.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
111
jscl/src/main/java/jscl/math/TechnicalVariable.java
Normal file
111
jscl/src/main/java/jscl/math/TechnicalVariable.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
9
jscl/src/main/java/jscl/math/TimeDependent.java
Normal file
9
jscl/src/main/java/jscl/math/TimeDependent.java
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package jscl.math;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 12/26/11
|
||||||
|
* Time: 10:23 AM
|
||||||
|
*/
|
||||||
|
public interface TimeDependent {
|
||||||
|
}
|
271
jscl/src/main/java/jscl/math/Variable.java
Normal file
271
jscl/src/main/java/jscl/math/Variable.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
14
jscl/src/main/java/jscl/math/VectorVariable.java
Normal file
14
jscl/src/main/java/jscl/math/VectorVariable.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
98
jscl/src/main/java/jscl/math/function/Abs.java
Normal file
98
jscl/src/main/java/jscl/math/function/Abs.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
103
jscl/src/main/java/jscl/math/function/AbstractDms.java
Normal file
103
jscl/src/main/java/jscl/math/function/AbstractDms.java
Normal 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!");
|
||||||
|
}
|
||||||
|
}
|
33
jscl/src/main/java/jscl/math/function/Algebraic.java
Normal file
33
jscl/src/main/java/jscl/math/function/Algebraic.java
Normal 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);
|
||||||
|
}
|
19
jscl/src/main/java/jscl/math/function/ArcTrigonometric.java
Normal file
19
jscl/src/main/java/jscl/math/function/ArcTrigonometric.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
106
jscl/src/main/java/jscl/math/function/Comparison.java
Normal file
106
jscl/src/main/java/jscl/math/function/Comparison.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
136
jscl/src/main/java/jscl/math/function/Conjugate.java
Normal file
136
jscl/src/main/java/jscl/math/function/Conjugate.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
269
jscl/src/main/java/jscl/math/function/Constant.java
Normal file
269
jscl/src/main/java/jscl/math/function/Constant.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
45
jscl/src/main/java/jscl/math/function/Constants.java
Normal file
45
jscl/src/main/java/jscl/math/function/Constants.java
Normal 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())));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
33
jscl/src/main/java/jscl/math/function/ConstantsRegistry.java
Normal file
33
jscl/src/main/java/jscl/math/function/ConstantsRegistry.java
Normal 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));
|
||||||
|
}
|
||||||
|
}
|
95
jscl/src/main/java/jscl/math/function/Cubic.java
Normal file
95
jscl/src/main/java/jscl/math/function/Cubic.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
333
jscl/src/main/java/jscl/math/function/CustomFunction.java
Normal file
333
jscl/src/main/java/jscl/math/function/CustomFunction.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
63
jscl/src/main/java/jscl/math/function/Deg.java
Normal file
63
jscl/src/main/java/jscl/math/function/Deg.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
40
jscl/src/main/java/jscl/math/function/Dms.java
Normal file
40
jscl/src/main/java/jscl/math/function/Dms.java
Normal 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);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
123
jscl/src/main/java/jscl/math/function/Exp.java
Normal file
123
jscl/src/main/java/jscl/math/function/Exp.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
226
jscl/src/main/java/jscl/math/function/ExtendedConstant.java
Normal file
226
jscl/src/main/java/jscl/math/function/ExtendedConstant.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
186
jscl/src/main/java/jscl/math/function/Fraction.java
Normal file
186
jscl/src/main/java/jscl/math/function/Fraction.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
101
jscl/src/main/java/jscl/math/function/Function.java
Normal file
101
jscl/src/main/java/jscl/math/function/Function.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
81
jscl/src/main/java/jscl/math/function/FunctionsRegistry.java
Normal file
81
jscl/src/main/java/jscl/math/function/FunctionsRegistry.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
31
jscl/src/main/java/jscl/math/function/IConstant.java
Normal file
31
jscl/src/main/java/jscl/math/function/IConstant.java
Normal 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();
|
||||||
|
}
|
21
jscl/src/main/java/jscl/math/function/IFunction.java
Normal file
21
jscl/src/main/java/jscl/math/function/IFunction.java
Normal 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();
|
||||||
|
}
|
273
jscl/src/main/java/jscl/math/function/ImplicitFunction.java
Normal file
273
jscl/src/main/java/jscl/math/function/ImplicitFunction.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
43
jscl/src/main/java/jscl/math/function/Inverse.java
Normal file
43
jscl/src/main/java/jscl/math/function/Inverse.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
86
jscl/src/main/java/jscl/math/function/Lg.java
Normal file
86
jscl/src/main/java/jscl/math/function/Lg.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
75
jscl/src/main/java/jscl/math/function/Ln.java
Normal file
75
jscl/src/main/java/jscl/math/function/Ln.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
10
jscl/src/main/java/jscl/math/function/NotRootException.java
Normal file
10
jscl/src/main/java/jscl/math/function/NotRootException.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package jscl.math.function;
|
||||||
|
|
||||||
|
public class NotRootException extends ArithmeticException {
|
||||||
|
public NotRootException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotRootException(String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
}
|
29
jscl/src/main/java/jscl/math/function/PiConstant.java
Normal file
29
jscl/src/main/java/jscl/math/function/PiConstant.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
289
jscl/src/main/java/jscl/math/function/Pow.java
Normal file
289
jscl/src/main/java/jscl/math/function/Pow.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
30
jscl/src/main/java/jscl/math/function/Rad.java
Normal file
30
jscl/src/main/java/jscl/math/function/Rad.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
419
jscl/src/main/java/jscl/math/function/Root.java
Normal file
419
jscl/src/main/java/jscl/math/function/Root.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
94
jscl/src/main/java/jscl/math/function/Sgn.java
Normal file
94
jscl/src/main/java/jscl/math/function/Sgn.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
179
jscl/src/main/java/jscl/math/function/Sqrt.java
Normal file
179
jscl/src/main/java/jscl/math/function/Sqrt.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
55
jscl/src/main/java/jscl/math/function/Trigonometric.java
Normal file
55
jscl/src/main/java/jscl/math/function/Trigonometric.java
Normal 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);
|
||||||
|
}
|
54
jscl/src/main/java/jscl/math/function/hyperbolic/Acosh.java
Normal file
54
jscl/src/main/java/jscl/math/function/hyperbolic/Acosh.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
55
jscl/src/main/java/jscl/math/function/hyperbolic/Acoth.java
Normal file
55
jscl/src/main/java/jscl/math/function/hyperbolic/Acoth.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
56
jscl/src/main/java/jscl/math/function/hyperbolic/Asinh.java
Normal file
56
jscl/src/main/java/jscl/math/function/hyperbolic/Asinh.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
57
jscl/src/main/java/jscl/math/function/hyperbolic/Atanh.java
Normal file
57
jscl/src/main/java/jscl/math/function/hyperbolic/Atanh.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
77
jscl/src/main/java/jscl/math/function/hyperbolic/Cosh.java
Normal file
77
jscl/src/main/java/jscl/math/function/hyperbolic/Cosh.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
75
jscl/src/main/java/jscl/math/function/hyperbolic/Coth.java
Normal file
75
jscl/src/main/java/jscl/math/function/hyperbolic/Coth.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
77
jscl/src/main/java/jscl/math/function/hyperbolic/Sinh.java
Normal file
77
jscl/src/main/java/jscl/math/function/hyperbolic/Sinh.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
81
jscl/src/main/java/jscl/math/function/hyperbolic/Tanh.java
Normal file
81
jscl/src/main/java/jscl/math/function/hyperbolic/Tanh.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
96
jscl/src/main/java/jscl/math/function/trigonometric/Cos.java
Normal file
96
jscl/src/main/java/jscl/math/function/trigonometric/Cos.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
75
jscl/src/main/java/jscl/math/function/trigonometric/Cot.java
Normal file
75
jscl/src/main/java/jscl/math/function/trigonometric/Cot.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
94
jscl/src/main/java/jscl/math/function/trigonometric/Sin.java
Normal file
94
jscl/src/main/java/jscl/math/function/trigonometric/Sin.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
103
jscl/src/main/java/jscl/math/function/trigonometric/Tan.java
Normal file
103
jscl/src/main/java/jscl/math/function/trigonometric/Tan.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
260
jscl/src/main/java/jscl/math/numeric/Complex.java
Normal file
260
jscl/src/main/java/jscl/math/numeric/Complex.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
114
jscl/src/main/java/jscl/math/numeric/INumeric.java
Normal file
114
jscl/src/main/java/jscl/math/numeric/INumeric.java
Normal 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();
|
||||||
|
}
|
312
jscl/src/main/java/jscl/math/numeric/Matrix.java
Normal file
312
jscl/src/main/java/jscl/math/numeric/Matrix.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
328
jscl/src/main/java/jscl/math/numeric/Numeric.java
Normal file
328
jscl/src/main/java/jscl/math/numeric/Numeric.java
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
280
jscl/src/main/java/jscl/math/numeric/Real.java
Normal file
280
jscl/src/main/java/jscl/math/numeric/Real.java
Normal 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
Loading…
Reference in New Issue
Block a user