Skip to content

Instantly share code, notes, and snippets.

@JarnaChao09
Created May 19, 2023 19:39
Show Gist options
  • Save JarnaChao09/aed7a12902a386617c05ef23facf4b54 to your computer and use it in GitHub Desktop.
Save JarnaChao09/aed7a12902a386617c05ef23facf4b54 to your computer and use it in GitHub Desktop.
// missing `}` before catch leads to error saying the code is a macro (???)
// unable to pass in dummy Unit struct as the argument list
// still errors as empty (???)
// unable to get around `Dynamic` use in first arg since it expects
// a Tuple and tuple literals do not work currently
// struct Unit {}
// func test(fun: Lambda<Dynamic, Dynamic, Dynamic>) {
// try {
// fun.invoke([Unit({})]);
// } catch (val e: Dynamic) {
// print("caught");
// }
// }
// test {
// print("hello");
// };
// zip must return List<List<T>> where List<T> is Pair<T, T> semantically
// Tuple is unable to have generic parameters
// Returning Tuples leads to other functions relying on zip
// to error on [] access since TupleInitializer.kt does not
// have any other functions defined on it
func zip<T>(list1: List<T>, list2: List<T>): List<List<T>> {
require list1.size == list2.size;
var ret = [];
range(0, list1.size, :incl_excl).for {
ret = ret + [[list1[val], list2[val]]];
};
ensure ret.size == list1.size && ret.size == list2.size;
return ret;
}
struct Vector {
val backing: List<Decimal>;
func size(this): Integer {
return this.backing.size;
}
// add, sub, mul, and div
// could have been generalized with Lambda<T, R, E>
// however, .invoke()/.invoke!() on Lambda types leads to
// a checked exception error (see test func at top of file)
// catching the exception
func add(this, other: Vector): Vector {
require this.size == other.size;
return Vector({
backing: this.backing.|zip(other.backing).map |pair| {
// caused NPE despite the lists having valid values at 0 and 1
// pair.first!() + pair.last!()
// using .value!() on first() errors with
// expected Result found Decimal
// initial guess after looking at ListInitializer.kt
// is first returns Type.NULLABLE instead of a
// Result type
pair[0] + pair[1]
}
});
}
func sub(this, other: Vector): Vector {
require this.size == other.size;
return Vector({
backing: this.backing.|zip(other.backing).map |pair| {
pair[0] - pair[1]
}
});
}
func mul(this, other: Vector): Vector {
require this.size == other.size;
return Vector({
backing: this.backing.|zip(other.backing).map |pair| {
pair[0] * pair[1]
}
});
}
func div(this, other: Vector): Vector {
require this.size == other.size;
for (val i in other.backing) {
require i != 0.0;
}
return Vector({
backing: this.backing.|zip(other.backing).map |pair| {
pair[0] / pair[1]
}
});
}
func reduceByAddition(this): Decimal {
require this.size != 0;
var ret = 0.0;
for (val e in this.backing) {
ret = ret + e;
}
return ret;
}
func dot(this, other: Vector): Decimal {
require this.size != 0 && this.size == other.size;
// unable to access val.result property
// printing out val leads to "{result=0.0, element=xxx}"
// return this.mul(other).reduce(0.0) { (val.result) + (val.element) };
return this.mul(other).reduceByAddition();
}
}
struct Shape {
val rows: Integer;
val columns: Integer;
}
struct Matrix {
val shape: Shape;
val backing: List<Decimal>;
// using init block leads to functions saying `this`
// is not initialized in rowCount and colCount
// error message does not aggregate and stops at the first function
// init(literal: List<List<Decimal>>) {
// require literal.size > 0;
// val rowCount = literal.size;
// val colCount = literal[0].size;
// var flattened = [];
// for (val row in literal) {
// require colCount == row.size;
// for (val e in row) {
// flattened = flattened + [e];
// }
// }
// this {
// shape: Shape({
// rows: rowCount,
// columns: colCount,
// }),
// backing: flattened,
// };
// }
func rowCount(this): Integer {
return this.shape.rows;
}
func columnCount(this): Integer {
return this.shape.columns;
}
func get(this, r: Integer, c: Integer): Decimal {
require r >= 0 && c >= 0;
require r * this.columnCount() + c < this.backing.size;
return this.backing[r * this.columnCount() + c];
}
func getRow(this, r: Integer): Vector {
require r >= 0;
var backing = [];
val startingIndex = r * this.columnCount();
range(startingIndex, startingIndex + this.columnCount(), :incl_excl).for {
backing = backing + [this.backing[val]];
};
return Vector({
backing: backing
});
}
func transpose(this): Matrix {
var flattened = [];
range(0, this.rowCount(), :incl_excl).for |i| {
range(0, this.columnCount(), :incl_excl).for |j| {
flattened = flattened + [this.get(j, i)];
};
};
return Matrix({
shape: Shape({
rows: this.columnCount(),
columns: this.rowCount(),
}),
backing: flattened,
});
}
func matmul(this, other: Matrix): Matrix {
require this.columnCount() == other.rowCount();
val newRowCount = this.columnCount();
val newColumnCount = other.rowCount();
val otherT = other.transpose();
var flattened = [];
range(0, this.rowCount(), :incl_excl).for |i| {
range(0, other.columnCount(), :incl_excl).for |j| {
flattened = flattened + [this.getRow(i).dot(otherT.getRow(j))];
};
};
return Matrix({
shape: Shape({
rows: newRowCount,
columns: newColumnCount,
}),
backing: flattened,
});
}
}
// trying to matrix function before definition in source is not possible
// Matrix struct will need to create everything with the builtin ctor
// since init blocks are causing uninitialized static analysis bug
// could be a static function (if possible)
func matrix(literal: List<List<Decimal>>): Matrix {
require literal.size > 0;
val rowCount = literal.size;
val colCount = literal[0].size;
var flattened = [];
for (val row in literal) {
require colCount == row.size;
for (val e in row) {
flattened = flattened + [e];
}
}
return Matrix({
shape: Shape({
rows: rowCount,
columns: colCount,
}),
backing: flattened,
});
}
val m1 = [[1.0, 2.0], [3.0, 4.0]].|matrix();
val m2 = [[3.0, 4.0], [5.0, 6.0]].|matrix();
print(m1);
print(m1.transpose());
print("");
print(m2);
print(m2.transpose());
print("");
print(m1.matmul(m2));
assert m1.matmul(m2) == [[13.0, 16.0], [29.0, 36.0]].|matrix();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment