Skip to content

Commit

Permalink
Quaternions kinda working, but qmake & qunmake are acting weird
Browse files Browse the repository at this point in the history
  • Loading branch information
kineticneticat committed Jun 6, 2024
1 parent 07881ef commit f091e13
Show file tree
Hide file tree
Showing 9 changed files with 167 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public static ComplexNumberIota deserialize(Tag tag) {
public static Component display(ComplexNumber cn) {
if (cn.real == 0) return Component.literal(String.format("%.2f", cn.imag) + "i").withStyle(ComplexNumberColour);
else
if (cn.imag > 0) return Component.literal(String.format("%.2f", cn.real) + " + " + String.format("%.2f", cn.imag) + "i").withStyle(ComplexNumberColour);
if (cn.imag >= 0) return Component.literal(String.format("%.2f", cn.real) + " + " + String.format("%.2f", cn.imag) + "i").withStyle(ComplexNumberColour);
else return Component.literal(String.format("%.2f", cn.real) + " - " + String.format("%.2f", Math.abs(cn.imag)) + "i").withStyle(ComplexNumberColour);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,15 @@ public static QuaternionIota deserialize(Tag tag) {
}
public static ChatFormatting QuaternionColour = ChatFormatting.DARK_BLUE;
public static Component display(Quaternion Q) {
if (Q.a+Q.c+Q.d==0) return Component.literal(String.format("%.2f", Q.b)).withStyle(QuaternionColour);
if (Q.a+Q.b+Q.d==0) return Component.literal(String.format("%.2f", Q.c)).withStyle(QuaternionColour);
if (Q.a+Q.b+Q.c==0) return Component.literal(String.format("%.2f", Q.d)).withStyle(QuaternionColour);
String text = String.format("%.2f", Q.a);
text += " " + (Q.b<0?"-":"+") + " " + String.format("%.2f", Math.abs(Q.b));
text += " " + (Q.c<0?"-":"+") + " " + String.format("%.2f", Math.abs(Q.c));
text += " " + (Q.d<0?"-":"+") + " " + String.format("%.2f", Math.abs(Q.d));
String text = "";
text += Q.a==0 ? "" : String.format("%.2f", Q.a);
text += text.equals("") ? ( Q.b==0 ? "" : String.format("%.2f", Q.b)+"i" )
: ( Q.b==0 ? "" : " " + (Q.b<0?"-":"+") + " " + String.format("%.2f", Math.abs(Q.b)) + "i" );
text += text.equals("") ? ( Q.c==0 ? "" : String.format("%.2f", Q.c)+"j" )
: ( Q.c==0 ? "" : " " + (Q.b<0?"-":"+") + " " + String.format("%.2f", Math.abs(Q.c)) + "j" );
text += text.equals("") ? ( Q.d==0 ? "" : String.format("%.2f", Q.d)+"k" )
: ( Q.d==0 ? "" : " " + (Q.b<0?"-":"+") + " " + String.format("%.2f", Math.abs(Q.d)) + "k" );
text = text.equals("") ? String.format("%.2f", 0.0d) : text;
return Component.literal(text).withStyle(QuaternionColour);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,33 @@ public class ComplexhexPatternRegistry {

public static final HexPattern CONGRATS = make("eed", HexDir.WEST, "congrats", new OpCongrats());
//Complex Arithmetic
public static final HexPattern CONST$COMPLEX$1$ = make("wqqa", HexDir.SOUTH_WEST, "const/complex/1",
Action.makeConstantOp(new ComplexNumber(1, 0).asIota()));
public static final HexPattern CONST$COMPLEX$I$ = make("wqq", HexDir.SOUTH_WEST, "const/complex/i",
Action.makeConstantOp(new ComplexNumber(0, 1).asIota()));
public static final HexPattern COMPLEXMUL = make("wqqewaqaw", HexDir.SOUTH_WEST, "complexmul");
public static final HexPattern REAL = make("wqqq", HexDir.SOUTH_WEST, "real");
public static final HexPattern IMAGINARY = make("wqqe", HexDir.SOUTH_WEST, "imaginary");
public static final HexPattern CONJUGATE = make("wqqd", HexDir.SOUTH_WEST, "conjugate");

// Quaternion Arithmetic
public static final HexPattern CONST$QUAT$I$ = make("deeeeeq", HexDir.SOUTH_EAST, "const/quat/i",
public static final HexPattern CONST$QUAT$1$ = make("deeeeeqa", HexDir.SOUTH_EAST, "const/quaternion/1",
Action.makeConstantOp(new Quaternion(1, 0, 0, 0).asIota()));
public static final HexPattern CONST$QUAT$I$ = make("deeeeeqq", HexDir.SOUTH_EAST, "const/quaternion/i",
Action.makeConstantOp(new Quaternion(0, 1, 0, 0).asIota()));
public static final HexPattern CONST$QUAT$J$ = make("deeeeeqe", HexDir.SOUTH_EAST, "const/quaternion/j",
Action.makeConstantOp(new Quaternion(0, 0, 1, 0).asIota()));
public static final HexPattern CONST$QUAT$K$ = make("deeeeeqd", HexDir.SOUTH_EAST, "const/quaternion/k",
Action.makeConstantOp(new Quaternion(0, 0, 0, 1).asIota()));
public static final HexPattern QMUL = make("deeeeeqwaqaw", HexDir.SOUTH_EAST, "qmul");
public static final HexPattern QINVERT = make("deeeeeqw", HexDir.SOUTH_EAST, "qinvert");
public static final HexPattern QA = make("deeeeeqaw", HexDir.SOUTH_EAST, "qa");
public static final HexPattern QB = make("deeeeeqqw", HexDir.SOUTH_EAST, "qb");
public static final HexPattern QC = make("deeeeeqew", HexDir.SOUTH_EAST, "qc");
public static final HexPattern QD = make("deeeeeqdw", HexDir.SOUTH_EAST, "qd");
public static final HexPattern QMAKE = make("deeeeeq", HexDir.SOUTH_EAST, "qmake");
public static final HexPattern QUNMAKE = make("aqqqqqe", HexDir.SOUTH_EAST, "qunmake");

public static void init() {
for (Map.Entry<ResourceLocation, ActionRegistryEntry> entry : PATTERNS.entrySet()) {
Registry.register(HexActions.REGISTRY, entry.getKey(), entry.getValue());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
import at.petrak.hexcasting.common.lib.hex.HexArithmetics;
import dev.kineticcat.complexhex.Complexhex;
import dev.kineticcat.complexhex.casting.arithmetic.complex.ComplexArithmetic;
import dev.kineticcat.complexhex.casting.arithmetic.quaternion.QuaternionArithmetic;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.LinkedHashMap;
import java.util.Map;

public class ComplexHexArithmetic {
public static final Logger LOGGER = LogManager.getLogger(Complexhex.MOD_ID);

private static final Map<ResourceLocation, Arithmetic> ARITHMETICS = new LinkedHashMap<>();

Expand All @@ -20,10 +24,11 @@ public static void init() {
}
}

public static ComplexArithmetic COMPLEX = make("complex", ComplexArithmetic.INSTANCE);
public static ComplexArithmetic COMPLEX = make(ComplexArithmetic.INSTANCE.arithName(), ComplexArithmetic.INSTANCE);
public static QuaternionArithmetic QUATERNION = make(QuaternionArithmetic.INSTANCE.arithName(), QuaternionArithmetic.INSTANCE);

private static <T extends Arithmetic> T make(String name, T arithmetic) {
var old = ARITHMETICS.put(new ResourceLocation(Complexhex.MOD_ID), arithmetic);
var old = ARITHMETICS.put(new ResourceLocation(Complexhex.MOD_ID, name), arithmetic);
if (old != null) {
throw new IllegalArgumentException("Typo? Duplicate id " + name);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import dev.kineticcat.complexhex.stuff.ComplexNumber
object ComplexArithmetic : Arithmetic {
private val ACCEPTS_C: IotaMultiPredicate = IotaMultiPredicate.all(IotaPredicate.ofType(ComplexHexIotaTypes.COMPLEXNUMBER))
private val ACCEPTS_CD: IotaMultiPredicate = IotaMultiPredicate.pair(IotaPredicate.ofType(ComplexHexIotaTypes.COMPLEXNUMBER), IotaPredicate.ofType(HexIotaTypes.DOUBLE))
private val ACCEPTS_CCorD: IotaMultiPredicate = IotaMultiPredicate.either(ACCEPTS_C, ACCEPTS_CD)
private val ACCEPTS_CCorCD: IotaMultiPredicate = IotaMultiPredicate.either(ACCEPTS_C, ACCEPTS_CD)
override fun arithName() = "complex_maths"
private val OPS = listOf(
ADD,
Expand All @@ -42,21 +42,21 @@ object ComplexArithmetic : Arithmetic {

override fun getOperator(pattern: HexPattern): Operator {
return when (pattern) {
ADD -> CDorCbinaryC({a, b -> a.add(b)}, {a, b -> a.add(b)})
SUB -> CDorCbinaryC({a, b -> a.sub(b)}, {a, b -> a.sub(b)})
MUL -> CDbinaryC {a, b -> a.mul(b)}
DIV -> CDbinaryC {a, b -> a.scalarDiv(b)}
ADD -> CDorCbinaryC({a, b -> a.add(b)}, {a, b -> a.add(b)})
SUB -> CDorCbinaryC({a, b -> a.sub(b)}, {a, b -> a.sub(b)})
MUL -> CDbinaryC {a, b -> a.mul(b)}
DIV -> CDbinaryC {a, b -> a.scalarDiv(b)}
COMPLEXMUL -> CCbinaryC {a, b -> a.mul(b)}
ABS -> CunaryD {a -> a.argument()}
REAL -> CunaryD {a -> a.real}
IMAGINARY -> CunaryD {a -> a.imag}
CONJUGATE -> CunaryC {a -> a.conjugate()}
ABS -> CunaryD {a -> a.argument()}
REAL -> CunaryD {a -> a.real}
IMAGINARY -> CunaryD {a -> a.imag}
CONJUGATE -> CunaryC {a -> a.conjugate()}
else -> throw InvalidOperatorException("$pattern is not a valid operator in complex arithmetic")
}
}

fun CunaryC(op: (ComplexNumber) -> (ComplexNumber)) = OperatorUnary(ACCEPTS_C)
{i: Iota -> ComplexNumberIota(op(Operator.downcast(i, ComplexHexIotaTypes.COMPLEXNUMBER).complex)) }
{i: Iota -> ComplexNumberIota(op(Operator.downcast(i, ComplexHexIotaTypes.COMPLEXNUMBER).complex)) }
fun CunaryD(op: (ComplexNumber) -> (Double)) = OperatorUnary(ACCEPTS_C)
{i: Iota -> DoubleIota(op(Operator.downcast(i, ComplexHexIotaTypes.COMPLEXNUMBER).complex))}

Expand All @@ -67,7 +67,7 @@ object ComplexArithmetic : Arithmetic {
private fun CDbinaryC(op: (ComplexNumber, Double) -> (ComplexNumber)) = OperatorBinary(ACCEPTS_CD)
{i: Iota, j: Iota -> ComplexNumberIota(op(Operator.downcast(i, ComplexHexIotaTypes.COMPLEXNUMBER).complex, Operator.downcast(j, HexIotaTypes.DOUBLE).double)) }
// what the fuck is this
fun CDorCbinaryC(opA:(ComplexNumber, ComplexNumber) -> (ComplexNumber), opB:(ComplexNumber, Double) -> (ComplexNumber)) = OperatorBinary(ACCEPTS_CCorD)
fun CDorCbinaryC(opA:(ComplexNumber, ComplexNumber) -> (ComplexNumber), opB:(ComplexNumber, Double) -> (ComplexNumber)) = OperatorBinary(ACCEPTS_CCorCD)
{i: Iota, j:Iota -> if (j is ComplexNumberIota) {
ComplexNumberIota(opA(Operator.downcast(i, ComplexHexIotaTypes.COMPLEXNUMBER).complex, Operator.downcast(j, ComplexHexIotaTypes.COMPLEXNUMBER).complex))
} else if (j is DoubleIota) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package dev.kineticcat.complexhex.casting.arithmetic.quaternion

import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator
import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBasic
import at.petrak.hexcasting.api.casting.castables.ConstMediaAction
import at.petrak.hexcasting.api.casting.asActionResult
import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
import at.petrak.hexcasting.api.casting.getDouble
import at.petrak.hexcasting.api.casting.iota.DoubleIota
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.casting.iota.Vec3Iota
import dev.kineticcat.complexhex.api.casting.iota.ComplexHexIotaTypes
import dev.kineticcat.complexhex.api.casting.iota.QuaternionIota
import dev.kineticcat.complexhex.stuff.Quaternion
import net.minecraft.world.phys.Vec3
import kotlin.math.sign

object OpQunmake : OperatorBasic(1, QuaternionArithmetic.ACCEPTS_Q) {
override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> {
val it = iotas.iterator()
val Q = Operator.downcast(it.next(), ComplexHexIotaTypes.QUATERNION).quaternion
return listOf(DoubleIota(Q.a), Vec3Iota(Vec3(Q.b, Q.c, Q.d)))
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package dev.kineticcat.complexhex.casting.arithmetic.quaternion

import at.petrak.hexcasting.api.casting.arithmetic.Arithmetic
import at.petrak.hexcasting.api.casting.arithmetic.Arithmetic.*
import at.petrak.hexcasting.api.casting.arithmetic.engine.InvalidOperatorException
import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator
import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBinary
import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorUnary
import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate
import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaPredicate
import at.petrak.hexcasting.api.casting.iota.DoubleIota
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.casting.math.HexPattern
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes
import dev.kineticcat.complexhex.Complexhex
import dev.kineticcat.complexhex.api.casting.iota.ComplexHexIotaTypes
import dev.kineticcat.complexhex.api.casting.iota.QuaternionIota
import dev.kineticcat.complexhex.casting.ComplexhexPatternRegistry.*
import dev.kineticcat.complexhex.stuff.Quaternion
import net.minecraft.world.phys.Vec3
import org.apache.logging.log4j.LogManager

object QuaternionArithmetic : Arithmetic {
val LOGGER = LogManager.getLogger(Complexhex.MOD_ID)

private val Q_PREDICATE = IotaPredicate.ofType(ComplexHexIotaTypes.QUATERNION)
private val D_PREDICATE = IotaPredicate.ofType(HexIotaTypes.DOUBLE)
private val V_PREDICATE = IotaPredicate.ofType(HexIotaTypes.VEC3)
public val ACCEPTS_Q: IotaMultiPredicate = IotaMultiPredicate.all(Q_PREDICATE)
private val ACCEPTS_QD: IotaMultiPredicate = IotaMultiPredicate.pair(Q_PREDICATE, D_PREDICATE)
private val ACCEPTS_DQ: IotaMultiPredicate = IotaMultiPredicate.pair(D_PREDICATE, Q_PREDICATE)
private val ACCEPTS_QQorQD: IotaMultiPredicate = IotaMultiPredicate.either(ACCEPTS_Q, ACCEPTS_QD)
private val ACCEPTS_DV: IotaMultiPredicate = IotaMultiPredicate.pair(D_PREDICATE, V_PREDICATE)
override fun arithName() = "quaternion_maths"
private val OPS = listOf(
ADD,
SUB,
MUL,
DIV,
QMUL,
QINVERT,
QA,
QB,
QC,
QD,
QMAKE,
QUNMAKE
)
override fun opTypes() = OPS

override fun getOperator(pattern: HexPattern?): Operator {
LOGGER.info(pattern)
return when (pattern) {
ADD -> QQorQDbinaryQ( { a, b -> a.add(b) }, { a, b -> a.add(b) } )
SUB -> QQorQDbinaryQ( { a, b -> a.sub(b) }, { a, b -> a.sub(b) } )
MUL -> QDbinaryQ { a, b -> a.mul(b) }
DIV -> QDbinaryQ { a, b -> a.div(b) }
QMUL -> QQbinaryQ { a, b -> a.mul(b) }
QINVERT -> QunaryQ { a -> a.inverse() }
QA -> QunaryD { a -> a.a }
QB -> QunaryD { a -> a.b }
QC -> QunaryD { a -> a.c }
QD -> QunaryD { a -> a.d }
QMAKE -> DVbinaryQ { d, v -> Quaternion(d, v.x, v.y, v.z) }
QUNMAKE -> OpQunmake
else -> throw InvalidOperatorException("$pattern is not a valid operator in quaternion arithmetic")
}
}

fun QunaryQ(op: (Quaternion) -> (Quaternion)) = OperatorUnary(ACCEPTS_Q)
{i: Iota -> op(Operator.downcast(i, ComplexHexIotaTypes.QUATERNION).quaternion).asIota() }
fun QunaryD(op: (Quaternion) -> (Double)) = OperatorUnary(ACCEPTS_Q)
{i: Iota -> DoubleIota(op(Operator.downcast(i, ComplexHexIotaTypes.QUATERNION).quaternion))}
fun QQbinaryQ(op: (Quaternion, Quaternion) -> (Quaternion)) = OperatorBinary(ACCEPTS_Q)
{i: Iota, j: Iota -> op(Operator.downcast(i, ComplexHexIotaTypes.QUATERNION).quaternion, Operator.downcast(j, ComplexHexIotaTypes.QUATERNION).quaternion).asIota() }
private fun QDbinaryQ(op: (Quaternion, Double) -> (Quaternion)) = OperatorBinary(ACCEPTS_QD)
{i: Iota, j: Iota -> op(Operator.downcast(i, ComplexHexIotaTypes.QUATERNION).quaternion, Operator.downcast(j, HexIotaTypes.DOUBLE).double).asIota() }
private fun QQorQDbinaryQ(opA:(Quaternion, Quaternion) -> (Quaternion), opB:(Quaternion, Double) -> (Quaternion)) = OperatorBinary(ACCEPTS_QQorQD)
{i: Iota, j:Iota -> if (j is QuaternionIota) {
opA(Operator.downcast(i, ComplexHexIotaTypes.QUATERNION).quaternion, Operator.downcast(j, ComplexHexIotaTypes.QUATERNION).quaternion).asIota()
} else if (j is DoubleIota) {
opB(Operator.downcast(i, ComplexHexIotaTypes.QUATERNION).quaternion, Operator.downcast(j, HexIotaTypes.DOUBLE).double).asIota()
} else {
throw InvalidOperatorException("i did an oopsie, report this pls :3 (${j::class})")
}
}
private fun DVbinaryQ(op: (Double, Vec3) -> Quaternion) = OperatorBinary(ACCEPTS_DV)
{i: Iota, j:Iota -> op(Operator.downcast(i, HexIotaTypes.DOUBLE).double, Operator.downcast(j, HexIotaTypes.VEC3).vec3).asIota()}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@ public static Quaternion angleAxis(double angle, Vec3 axis) {
public QuaternionIota asIota() { return new QuaternionIota(this);}
public static Quaternion fixNaN(Quaternion Q) {return new Quaternion(HexUtils.fixNAN(Q.a), HexUtils.fixNAN(Q.b), HexUtils.fixNAN(Q.c), HexUtils.fixNAN(Q.d));}
public Quaternion add(Quaternion B) { return new Quaternion(this.a + B.a, this.b + B.b, this.c + B.c, this.d + B.d); }
public Quaternion add(Double B) { return new Quaternion(this.a + B, this.b, this.c, this.d); }
public Quaternion sub(Quaternion B) { return new Quaternion(this.a - B.a, this.b - B.b, this.c - B.c, this.d - B.d); }
public Quaternion sub(Double B) { return new Quaternion(this.a - B, this.b, this.c, this.d); }
public Quaternion mul(double B) { return new Quaternion(this.a * B, this.b * B, this.c * B, this.d * B); }
public Quaternion div(double B) { return new Quaternion(this.a / B, this.b / B, this.c / B, this.d / B); }
public Quaternion mul(Quaternion B) { Quaternion A = this; return new Quaternion(
(A.a*B.a - A.b*B.b - A.c*B.c - A.d*B.d),
(A.a*B.b + A.b*B.a + A.c*B.d - A.d*B.c),
Expand Down
10 changes: 2 additions & 8 deletions common/src/main/resources/assets/complexhex/lang/en_us.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
{
"item.complexhex.dummy_item": "Dummy Item",
"hexcasting.action.complexhex:congrats": "Congrats",
"hexcasting.action.complexhex:signum": "Signum Purification",
"hexcasting.action.book.complexhex:congrats": "Dum. Spell Actn.",
"hexcasting.action.book.complexhex:const/complex/i": "Constant Imagination",
"complexhex.entry.complex_spells": "Dummy Spells",
"complexhex.entry.complex_actions": "Complexities",
"complexhex.page.complex_spells.congrats": "Accepts a player entity, tells them they are doing a good job and makes them look up.",
"complexhex.page.complex_actions.const.i": "Pushes 0 + 1i to the stack",
"text.complexhex.congrats": "Good job, %1$s!",
"text.complexhex.congrats.player": "a Player"


}

0 comments on commit f091e13

Please sign in to comment.