Skip to content

Commit

Permalink
Merge pull request #465 from the-qa-company/GH-464-log-func
Browse files Browse the repository at this point in the history
  • Loading branch information
ate47 authored Mar 27, 2024
2 parents 7a56479 + d532b77 commit 147d4f1
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.the_qa_company.qendpoint.functions;

import com.the_qa_company.qendpoint.store.EndpointStore;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.base.CoreDatatype;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.function.Function;

public class Log implements Function {
@Override
public String getURI() {
return EndpointStore.BASE_URI + "log";
}

@Override
public Value evaluate(ValueFactory valueFactory, Value... args) throws ValueExprEvaluationException {
if (args.length < 1 || args.length > 2) {
throw new ValueExprEvaluationException(getURI() + "(value, base = 10)");
}

Value valueVal = args[0];

if (!valueVal.isLiteral() || !(valueVal instanceof Literal lit)) {
throw new ValueExprEvaluationException(getURI() + " : value should be a literal");
}
CoreDatatype cdt = lit.getCoreDatatype();

if (!cdt.isXSDDatatype() || !cdt.asXSDDatatype().orElseThrow().isNumericDatatype()) {
throw new ValueExprEvaluationException(getURI() + " : value should be a numeric literal");
}

double val = lit.doubleValue();

if (val <= 0) {
throw new ValueExprEvaluationException(getURI() + " : value should be a positive number");
}

int base;

if (args.length >= 2) {
Value baseVal = args[1];

if (!baseVal.isLiteral() || !(baseVal instanceof Literal litb)) {
throw new ValueExprEvaluationException(getURI() + " : base should be a literal");
}
CoreDatatype bcdt = litb.getCoreDatatype();

if (!bcdt.isXSDDatatype() || !bcdt.asXSDDatatype().orElseThrow().isIntegerDatatype()) {
throw new ValueExprEvaluationException(getURI() + " : base should be an int literal");
}

base = litb.intValue();
} else {
base = 10;
}
if (base == 10) {
return valueFactory.createLiteral(Math.log10(val));
}
return valueFactory.createLiteral(Math.log(val) / Math.log(base));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import com.the_qa_company.qendpoint.model.HDTValue;
import com.the_qa_company.qendpoint.utils.BitArrayDisk;
import com.the_qa_company.qendpoint.utils.CloseSafeHDT;
import com.the_qa_company.qendpoint.utils.OverrideHDTOptions;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.file.PathUtils;
import org.eclipse.rdf4j.common.concurrent.locks.Lock;
Expand Down Expand Up @@ -66,6 +65,10 @@
import java.util.concurrent.atomic.AtomicReference;

public class EndpointStore extends AbstractNotifyingSail {
/**
* base uri
*/
public static final String BASE_URI = "http://the-qa-company.com/qendpoint/#";
/**
* disable the optimizer
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
com.the_qa_company.qendpoint.functions.ParseDateFunction
com.the_qa_company.qendpoint.functions.ParseDateFunction
com.the_qa_company.qendpoint.functions.Log
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.the_qa_company.qendpoint.functions;

import com.the_qa_company.qendpoint.store.EndpointStore;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.query.TupleQueryResult;
import org.eclipse.rdf4j.repository.sail.SailRepository;
import org.eclipse.rdf4j.repository.util.Repositories;
import org.eclipse.rdf4j.sail.memory.MemoryStore;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class LogTest {
@Test
public void funcTest() {
MemoryStore ms = new MemoryStore();
SailRepository repo = new SailRepository(ms);
repo.init();
try {
Repositories.consumeNoTransaction(repo, conn -> {
try (TupleQueryResult res = conn.prepareTupleQuery("""
PREFIX qep: <%s>
SELECT * {
VALUES ?number { 10 80 420 10000 20000 1000000 }
BIND (qep:log(?number) AS ?logNumberDef)
BIND (qep:log(?number, 10) AS ?logNumber10)
BIND (qep:log(?number, 16) AS ?logNumber16)
BIND (qep:log(?number, 2) AS ?logNumber2)
}
""".formatted(EndpointStore.BASE_URI)).evaluate()) {
res.forEach(bind -> {
double value = ((Literal) bind.getValue("number")).doubleValue();

assertEquals(((Literal) bind.getValue("logNumberDef")).doubleValue(), Math.log10(value), 0.001);
assertEquals(((Literal) bind.getValue("logNumber10")).doubleValue(), Math.log10(value), 0.001);
assertEquals(((Literal) bind.getValue("logNumber16")).doubleValue(),
Math.log10(value) / Math.log10(16), 0.001);
assertEquals(((Literal) bind.getValue("logNumber2")).doubleValue(),
Math.log10(value) / Math.log10(2), 0.001);
});
}
});
} finally {
repo.shutDown();
}
}

}

0 comments on commit 147d4f1

Please sign in to comment.