Browse Source

Add trigonometric functions (ESQL-1513)

This adds `SIN`, `COS`, `TAN`, `SINH`, `COSH`, and `TANH` functions.

---------

Co-authored-by: Abdon Pijpelink <abdon.pijpelink@elastic.co>
Nik Everett 2 years ago
parent
commit
c44a245cae
31 changed files with 1272 additions and 0 deletions
  1. 12 0
      docs/reference/esql/esql-functions.asciidoc
  2. 12 0
      docs/reference/esql/functions/cos.asciidoc
  3. 12 0
      docs/reference/esql/functions/cosh.asciidoc
  4. 12 0
      docs/reference/esql/functions/sin.asciidoc
  5. 12 0
      docs/reference/esql/functions/sinh.asciidoc
  6. 12 0
      docs/reference/esql/functions/tan.asciidoc
  7. 12 0
      docs/reference/esql/functions/tanh.asciidoc
  8. 78 0
      x-pack/plugin/esql/qa/testFixtures/src/main/resources/floats.csv-spec
  9. 42 0
      x-pack/plugin/esql/qa/testFixtures/src/main/resources/ints.csv-spec
  10. 6 0
      x-pack/plugin/esql/qa/testFixtures/src/main/resources/show.csv-spec
  11. 64 0
      x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/function/scalar/math/CosEvaluator.java
  12. 64 0
      x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/function/scalar/math/CoshEvaluator.java
  13. 64 0
      x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/function/scalar/math/SinEvaluator.java
  14. 64 0
      x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/function/scalar/math/SinhEvaluator.java
  15. 64 0
      x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/function/scalar/math/TanEvaluator.java
  16. 64 0
      x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/function/scalar/math/TanhEvaluator.java
  17. 12 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java
  18. 60 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AbstractTrigonometricFunction.java
  19. 45 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Cos.java
  20. 45 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Cosh.java
  21. 45 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Sin.java
  22. 45 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Sinh.java
  23. 45 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Tan.java
  24. 45 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Tanh.java
  25. 18 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/io/stream/PlanNamedTypes.java
  26. 53 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/CosTests.java
  27. 53 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/CoshTests.java
  28. 53 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/SinTests.java
  29. 53 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/SinhTests.java
  30. 53 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/TanTests.java
  31. 53 0
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/TanhTests.java

+ 12 - 0
docs/reference/esql/esql-functions.asciidoc

@@ -13,6 +13,8 @@ these functions:
 * <<esql-case>>
 * <<esql-cidr_match>>
 * <<esql-concat>>
+* <<esql-cos>>
+* <<esql-cosh>>
 * <<esql-date_extract>>
 * <<esql-date_format>>
 * <<esql-date_parse>>
@@ -37,9 +39,13 @@ these functions:
 * <<esql-pi>>
 * <<esql-pow>>
 * <<esql-round>>
+* <<esql-sin>>
+* <<esql-sinh>>
 * <<esql-split>>
 * <<esql-starts_with>>
 * <<esql-substring>>
+* <<esql-tan>>
+* <<esql-tanh>>
 * <<esql-tau>>
 * <<esql-to_boolean>>
 * <<esql-to_datetime>>
@@ -57,6 +63,8 @@ include::functions/auto_bucket.asciidoc[]
 include::functions/case.asciidoc[]
 include::functions/cidr_match.asciidoc[]
 include::functions/concat.asciidoc[]
+include::functions/cos.asciidoc[]
+include::functions/cosh.asciidoc[]
 include::functions/date_extract.asciidoc[]
 include::functions/date_format.asciidoc[]
 include::functions/date_parse.asciidoc[]
@@ -81,9 +89,13 @@ include::functions/now.asciidoc[]
 include::functions/pi.asciidoc[]
 include::functions/pow.asciidoc[]
 include::functions/round.asciidoc[]
+include::functions/sin.asciidoc[]
+include::functions/sinh.asciidoc[]
 include::functions/split.asciidoc[]
 include::functions/starts_with.asciidoc[]
 include::functions/substring.asciidoc[]
+include::functions/tan.asciidoc[]
+include::functions/tanh.asciidoc[]
 include::functions/tau.asciidoc[]
 include::functions/to_boolean.asciidoc[]
 include::functions/to_datetime.asciidoc[]

+ 12 - 0
docs/reference/esql/functions/cos.asciidoc

@@ -0,0 +1,12 @@
+[[esql-cos]]
+=== `COS`
+https://en.wikipedia.org/wiki/Sine_and_cosine[Cosine] trigonometric function.
+
+[source.merge.styled,esql]
+----
+include::{esql-specs}/floats.csv-spec[tag=cos]
+----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/floats.csv-spec[tag=cos-result]
+|===

+ 12 - 0
docs/reference/esql/functions/cosh.asciidoc

@@ -0,0 +1,12 @@
+[[esql-cosh]]
+=== `COSH`
+https://en.wikipedia.org/wiki/Hyperbolic_functions[Cosine] hyperbolic function.
+
+[source.merge.styled,esql]
+----
+include::{esql-specs}/floats.csv-spec[tag=cosh]
+----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/floats.csv-spec[tag=cosh-result]
+|===

+ 12 - 0
docs/reference/esql/functions/sin.asciidoc

@@ -0,0 +1,12 @@
+[[esql-sin]]
+=== `SIN`
+https://en.wikipedia.org/wiki/Sine_and_cosine[Sine] trigonometric function.
+
+[source.merge.styled,esql]
+----
+include::{esql-specs}/floats.csv-spec[tag=sin]
+----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/floats.csv-spec[tag=sin-result]
+|===

+ 12 - 0
docs/reference/esql/functions/sinh.asciidoc

@@ -0,0 +1,12 @@
+[[esql-sinh]]
+=== `SINH`
+https://en.wikipedia.org/wiki/Hyperbolic_functions[Sine] hyperbolic function.
+
+[source.merge.styled,esql]
+----
+include::{esql-specs}/floats.csv-spec[tag=sinh]
+----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/floats.csv-spec[tag=sinh-result]
+|===

+ 12 - 0
docs/reference/esql/functions/tan.asciidoc

@@ -0,0 +1,12 @@
+[[esql-tan]]
+=== `TAN`
+https://en.wikipedia.org/wiki/Sine_and_cosine[Tangent] trigonometric function.
+
+[source.merge.styled,esql]
+----
+include::{esql-specs}/floats.csv-spec[tag=tan]
+----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/floats.csv-spec[tag=tan-result]
+|===

+ 12 - 0
docs/reference/esql/functions/tanh.asciidoc

@@ -0,0 +1,12 @@
+[[esql-tanh]]
+=== `TANH`
+https://en.wikipedia.org/wiki/Hyperbolic_functions[Tangent] hyperbolic function.
+
+[source.merge.styled,esql]
+----
+include::{esql-specs}/floats.csv-spec[tag=tanh]
+----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/floats.csv-spec[tag=tanh-result]
+|===

+ 78 - 0
x-pack/plugin/esql/qa/testFixtures/src/main/resources/floats.csv-spec

@@ -230,3 +230,81 @@ hire_date:date           | height:double | bh:double
 1985-11-20T00:00:00.000Z | 1.93          | 1.9000000000000001
 1985-11-21T00:00:00.000Z | 2.08          | 2.0500000000000003
 ;
+
+cos
+// tag::cos[]
+ROW a=1.8 
+| EVAL cos=COS(a)
+// end::cos[]
+;
+
+// tag::cos-result[]
+a:double | cos:double
+     1.8 | -0.2272020946930871
+// end::cos-result[]
+;
+
+cosh
+// tag::cosh[]
+ROW a=1.8 
+| EVAL cosh=COSH(a)
+// end::cosh[]
+;
+
+// tag::cosh-result[]
+a:double | cosh:double
+     1.8 | 3.1074731763172667
+// end::cosh-result[]
+;
+
+sin
+// tag::sin[]
+ROW a=1.8 
+| EVAL sin=SIN(a)
+// end::sin[]
+;
+
+// tag::sin-result[]
+a:double | sin:double
+     1.8 | 0.9738476308781951
+// end::sin-result[]
+;
+
+sinh
+// tag::sinh[]
+ROW a=1.8 
+| EVAL sinh=SINH(a)
+// end::sinh[]
+;
+
+// tag::sinh-result[]
+a:double | sinh:double
+     1.8 | 2.94217428809568
+// end::sinh-result[]
+;
+
+tan
+// tag::tan[]
+ROW a=1.8 
+| EVAL tan=TAN(a)
+// end::tan[]
+;
+
+// tag::tan-result[]
+a:double | tan:double
+     1.8 | -4.286261674628062
+// end::tan-result[]
+;
+
+tanh
+// tag::tanh[]
+ROW a=1.8 
+| EVAL tanh=TANH(a)
+// end::tanh[]
+;
+
+// tag::tanh-result[]
+a:double | tanh:double
+     1.8 | 0.9468060128462683
+// end::tanh-result[]
+;

+ 42 - 0
x-pack/plugin/esql/qa/testFixtures/src/main/resources/ints.csv-spec

@@ -380,3 +380,45 @@ hire_date:date           | salary:integer | bs:double
 1985-11-21T00:00:00.000Z | 56371          | 55000.0
 // end::auto_bucket-result[]
 ;
+
+cos
+ROW a=2 | EVAL cos=COS(a);
+
+a:integer | cos:double
+        2 | -0.4161468365471424
+;
+
+cosh
+ROW a=2 | EVAL cosh=COSH(a);
+
+a:integer | cosh:double
+        2 | 3.7621956910836314
+;
+
+sin
+ROW a=2 | EVAL sin=SIN(a);
+
+a:integer | sin:double
+        2 | 0.9092974268256817
+;
+
+sinh
+ROW a=2 | EVAL sinh=SINH(a);
+
+a:integer | sinh:double
+        2 | 3.626860407847019
+;
+
+tan
+ROW a=2 | EVAL tan=TAN(a);
+
+a:integer | tan:double
+        2 | -2.185039863261519
+;
+
+tanh
+ROW a=2 | EVAL tanh=TANH(a);
+
+a:integer | tanh:double
+        2 | 0.9640275800758169
+;

+ 6 - 0
x-pack/plugin/esql/qa/testFixtures/src/main/resources/show.csv-spec

@@ -15,6 +15,8 @@ avg                      |avg(arg1)
 case                     |case(arg1...)
 cidr_match               |cidr_match(arg1, arg2...)
 concat                   |concat(arg1, arg2...)
+cos                      |cos(arg1)
+cosh                     |cosh(arg1)
 count                    |count(arg1)
 count_distinct           |count_distinct(arg1, arg2)
 date_extract             |date_extract(arg1, arg2)
@@ -46,10 +48,14 @@ percentile               |percentile(arg1, arg2)
 pi                       |pi()
 pow                      |pow(arg1, arg2)
 round                    |round(arg1, arg2)
+sin                      |sin(arg1)
+sinh                     |sinh(arg1)
 split                    |split(arg1, arg2)
 starts_with              |starts_with(arg1, arg2)
 substring                |substring(arg1, arg2, arg3)
 sum                      |sum(arg1)
+tan                      |tan(arg1)
+tanh                     |tanh(arg1)
 tau                      |tau()
 to_bool                  |to_bool(arg1)
 to_boolean               |to_boolean(arg1)

+ 64 - 0
x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/function/scalar/math/CosEvaluator.java

@@ -0,0 +1,64 @@
+// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+// or more contributor license agreements. Licensed under the Elastic License
+// 2.0; you may not use this file except in compliance with the Elastic License
+// 2.0.
+package org.elasticsearch.xpack.esql.expression.function.scalar.math;
+
+import java.lang.Override;
+import java.lang.String;
+import org.elasticsearch.compute.data.Block;
+import org.elasticsearch.compute.data.DoubleBlock;
+import org.elasticsearch.compute.data.DoubleVector;
+import org.elasticsearch.compute.data.Page;
+import org.elasticsearch.compute.operator.EvalOperator;
+
+/**
+ * {@link EvalOperator.ExpressionEvaluator} implementation for {@link Cos}.
+ * This class is generated. Do not edit it.
+ */
+public final class CosEvaluator implements EvalOperator.ExpressionEvaluator {
+  private final EvalOperator.ExpressionEvaluator val;
+
+  public CosEvaluator(EvalOperator.ExpressionEvaluator val) {
+    this.val = val;
+  }
+
+  @Override
+  public Block eval(Page page) {
+    Block valUncastBlock = val.eval(page);
+    if (valUncastBlock.areAllValuesNull()) {
+      return Block.constantNullBlock(page.getPositionCount());
+    }
+    DoubleBlock valBlock = (DoubleBlock) valUncastBlock;
+    DoubleVector valVector = valBlock.asVector();
+    if (valVector == null) {
+      return eval(page.getPositionCount(), valBlock);
+    }
+    return eval(page.getPositionCount(), valVector).asBlock();
+  }
+
+  public DoubleBlock eval(int positionCount, DoubleBlock valBlock) {
+    DoubleBlock.Builder result = DoubleBlock.newBlockBuilder(positionCount);
+    position: for (int p = 0; p < positionCount; p++) {
+      if (valBlock.isNull(p) || valBlock.getValueCount(p) != 1) {
+        result.appendNull();
+        continue position;
+      }
+      result.appendDouble(Cos.process(valBlock.getDouble(valBlock.getFirstValueIndex(p))));
+    }
+    return result.build();
+  }
+
+  public DoubleVector eval(int positionCount, DoubleVector valVector) {
+    DoubleVector.Builder result = DoubleVector.newVectorBuilder(positionCount);
+    position: for (int p = 0; p < positionCount; p++) {
+      result.appendDouble(Cos.process(valVector.getDouble(p)));
+    }
+    return result.build();
+  }
+
+  @Override
+  public String toString() {
+    return "CosEvaluator[" + "val=" + val + "]";
+  }
+}

+ 64 - 0
x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/function/scalar/math/CoshEvaluator.java

@@ -0,0 +1,64 @@
+// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+// or more contributor license agreements. Licensed under the Elastic License
+// 2.0; you may not use this file except in compliance with the Elastic License
+// 2.0.
+package org.elasticsearch.xpack.esql.expression.function.scalar.math;
+
+import java.lang.Override;
+import java.lang.String;
+import org.elasticsearch.compute.data.Block;
+import org.elasticsearch.compute.data.DoubleBlock;
+import org.elasticsearch.compute.data.DoubleVector;
+import org.elasticsearch.compute.data.Page;
+import org.elasticsearch.compute.operator.EvalOperator;
+
+/**
+ * {@link EvalOperator.ExpressionEvaluator} implementation for {@link Cosh}.
+ * This class is generated. Do not edit it.
+ */
+public final class CoshEvaluator implements EvalOperator.ExpressionEvaluator {
+  private final EvalOperator.ExpressionEvaluator val;
+
+  public CoshEvaluator(EvalOperator.ExpressionEvaluator val) {
+    this.val = val;
+  }
+
+  @Override
+  public Block eval(Page page) {
+    Block valUncastBlock = val.eval(page);
+    if (valUncastBlock.areAllValuesNull()) {
+      return Block.constantNullBlock(page.getPositionCount());
+    }
+    DoubleBlock valBlock = (DoubleBlock) valUncastBlock;
+    DoubleVector valVector = valBlock.asVector();
+    if (valVector == null) {
+      return eval(page.getPositionCount(), valBlock);
+    }
+    return eval(page.getPositionCount(), valVector).asBlock();
+  }
+
+  public DoubleBlock eval(int positionCount, DoubleBlock valBlock) {
+    DoubleBlock.Builder result = DoubleBlock.newBlockBuilder(positionCount);
+    position: for (int p = 0; p < positionCount; p++) {
+      if (valBlock.isNull(p) || valBlock.getValueCount(p) != 1) {
+        result.appendNull();
+        continue position;
+      }
+      result.appendDouble(Cosh.process(valBlock.getDouble(valBlock.getFirstValueIndex(p))));
+    }
+    return result.build();
+  }
+
+  public DoubleVector eval(int positionCount, DoubleVector valVector) {
+    DoubleVector.Builder result = DoubleVector.newVectorBuilder(positionCount);
+    position: for (int p = 0; p < positionCount; p++) {
+      result.appendDouble(Cosh.process(valVector.getDouble(p)));
+    }
+    return result.build();
+  }
+
+  @Override
+  public String toString() {
+    return "CoshEvaluator[" + "val=" + val + "]";
+  }
+}

+ 64 - 0
x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/function/scalar/math/SinEvaluator.java

@@ -0,0 +1,64 @@
+// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+// or more contributor license agreements. Licensed under the Elastic License
+// 2.0; you may not use this file except in compliance with the Elastic License
+// 2.0.
+package org.elasticsearch.xpack.esql.expression.function.scalar.math;
+
+import java.lang.Override;
+import java.lang.String;
+import org.elasticsearch.compute.data.Block;
+import org.elasticsearch.compute.data.DoubleBlock;
+import org.elasticsearch.compute.data.DoubleVector;
+import org.elasticsearch.compute.data.Page;
+import org.elasticsearch.compute.operator.EvalOperator;
+
+/**
+ * {@link EvalOperator.ExpressionEvaluator} implementation for {@link Sin}.
+ * This class is generated. Do not edit it.
+ */
+public final class SinEvaluator implements EvalOperator.ExpressionEvaluator {
+  private final EvalOperator.ExpressionEvaluator val;
+
+  public SinEvaluator(EvalOperator.ExpressionEvaluator val) {
+    this.val = val;
+  }
+
+  @Override
+  public Block eval(Page page) {
+    Block valUncastBlock = val.eval(page);
+    if (valUncastBlock.areAllValuesNull()) {
+      return Block.constantNullBlock(page.getPositionCount());
+    }
+    DoubleBlock valBlock = (DoubleBlock) valUncastBlock;
+    DoubleVector valVector = valBlock.asVector();
+    if (valVector == null) {
+      return eval(page.getPositionCount(), valBlock);
+    }
+    return eval(page.getPositionCount(), valVector).asBlock();
+  }
+
+  public DoubleBlock eval(int positionCount, DoubleBlock valBlock) {
+    DoubleBlock.Builder result = DoubleBlock.newBlockBuilder(positionCount);
+    position: for (int p = 0; p < positionCount; p++) {
+      if (valBlock.isNull(p) || valBlock.getValueCount(p) != 1) {
+        result.appendNull();
+        continue position;
+      }
+      result.appendDouble(Sin.process(valBlock.getDouble(valBlock.getFirstValueIndex(p))));
+    }
+    return result.build();
+  }
+
+  public DoubleVector eval(int positionCount, DoubleVector valVector) {
+    DoubleVector.Builder result = DoubleVector.newVectorBuilder(positionCount);
+    position: for (int p = 0; p < positionCount; p++) {
+      result.appendDouble(Sin.process(valVector.getDouble(p)));
+    }
+    return result.build();
+  }
+
+  @Override
+  public String toString() {
+    return "SinEvaluator[" + "val=" + val + "]";
+  }
+}

+ 64 - 0
x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/function/scalar/math/SinhEvaluator.java

@@ -0,0 +1,64 @@
+// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+// or more contributor license agreements. Licensed under the Elastic License
+// 2.0; you may not use this file except in compliance with the Elastic License
+// 2.0.
+package org.elasticsearch.xpack.esql.expression.function.scalar.math;
+
+import java.lang.Override;
+import java.lang.String;
+import org.elasticsearch.compute.data.Block;
+import org.elasticsearch.compute.data.DoubleBlock;
+import org.elasticsearch.compute.data.DoubleVector;
+import org.elasticsearch.compute.data.Page;
+import org.elasticsearch.compute.operator.EvalOperator;
+
+/**
+ * {@link EvalOperator.ExpressionEvaluator} implementation for {@link Sinh}.
+ * This class is generated. Do not edit it.
+ */
+public final class SinhEvaluator implements EvalOperator.ExpressionEvaluator {
+  private final EvalOperator.ExpressionEvaluator val;
+
+  public SinhEvaluator(EvalOperator.ExpressionEvaluator val) {
+    this.val = val;
+  }
+
+  @Override
+  public Block eval(Page page) {
+    Block valUncastBlock = val.eval(page);
+    if (valUncastBlock.areAllValuesNull()) {
+      return Block.constantNullBlock(page.getPositionCount());
+    }
+    DoubleBlock valBlock = (DoubleBlock) valUncastBlock;
+    DoubleVector valVector = valBlock.asVector();
+    if (valVector == null) {
+      return eval(page.getPositionCount(), valBlock);
+    }
+    return eval(page.getPositionCount(), valVector).asBlock();
+  }
+
+  public DoubleBlock eval(int positionCount, DoubleBlock valBlock) {
+    DoubleBlock.Builder result = DoubleBlock.newBlockBuilder(positionCount);
+    position: for (int p = 0; p < positionCount; p++) {
+      if (valBlock.isNull(p) || valBlock.getValueCount(p) != 1) {
+        result.appendNull();
+        continue position;
+      }
+      result.appendDouble(Sinh.process(valBlock.getDouble(valBlock.getFirstValueIndex(p))));
+    }
+    return result.build();
+  }
+
+  public DoubleVector eval(int positionCount, DoubleVector valVector) {
+    DoubleVector.Builder result = DoubleVector.newVectorBuilder(positionCount);
+    position: for (int p = 0; p < positionCount; p++) {
+      result.appendDouble(Sinh.process(valVector.getDouble(p)));
+    }
+    return result.build();
+  }
+
+  @Override
+  public String toString() {
+    return "SinhEvaluator[" + "val=" + val + "]";
+  }
+}

+ 64 - 0
x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/function/scalar/math/TanEvaluator.java

@@ -0,0 +1,64 @@
+// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+// or more contributor license agreements. Licensed under the Elastic License
+// 2.0; you may not use this file except in compliance with the Elastic License
+// 2.0.
+package org.elasticsearch.xpack.esql.expression.function.scalar.math;
+
+import java.lang.Override;
+import java.lang.String;
+import org.elasticsearch.compute.data.Block;
+import org.elasticsearch.compute.data.DoubleBlock;
+import org.elasticsearch.compute.data.DoubleVector;
+import org.elasticsearch.compute.data.Page;
+import org.elasticsearch.compute.operator.EvalOperator;
+
+/**
+ * {@link EvalOperator.ExpressionEvaluator} implementation for {@link Tan}.
+ * This class is generated. Do not edit it.
+ */
+public final class TanEvaluator implements EvalOperator.ExpressionEvaluator {
+  private final EvalOperator.ExpressionEvaluator val;
+
+  public TanEvaluator(EvalOperator.ExpressionEvaluator val) {
+    this.val = val;
+  }
+
+  @Override
+  public Block eval(Page page) {
+    Block valUncastBlock = val.eval(page);
+    if (valUncastBlock.areAllValuesNull()) {
+      return Block.constantNullBlock(page.getPositionCount());
+    }
+    DoubleBlock valBlock = (DoubleBlock) valUncastBlock;
+    DoubleVector valVector = valBlock.asVector();
+    if (valVector == null) {
+      return eval(page.getPositionCount(), valBlock);
+    }
+    return eval(page.getPositionCount(), valVector).asBlock();
+  }
+
+  public DoubleBlock eval(int positionCount, DoubleBlock valBlock) {
+    DoubleBlock.Builder result = DoubleBlock.newBlockBuilder(positionCount);
+    position: for (int p = 0; p < positionCount; p++) {
+      if (valBlock.isNull(p) || valBlock.getValueCount(p) != 1) {
+        result.appendNull();
+        continue position;
+      }
+      result.appendDouble(Tan.process(valBlock.getDouble(valBlock.getFirstValueIndex(p))));
+    }
+    return result.build();
+  }
+
+  public DoubleVector eval(int positionCount, DoubleVector valVector) {
+    DoubleVector.Builder result = DoubleVector.newVectorBuilder(positionCount);
+    position: for (int p = 0; p < positionCount; p++) {
+      result.appendDouble(Tan.process(valVector.getDouble(p)));
+    }
+    return result.build();
+  }
+
+  @Override
+  public String toString() {
+    return "TanEvaluator[" + "val=" + val + "]";
+  }
+}

+ 64 - 0
x-pack/plugin/esql/src/main/java/generated/org/elasticsearch/xpack/esql/expression/function/scalar/math/TanhEvaluator.java

@@ -0,0 +1,64 @@
+// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+// or more contributor license agreements. Licensed under the Elastic License
+// 2.0; you may not use this file except in compliance with the Elastic License
+// 2.0.
+package org.elasticsearch.xpack.esql.expression.function.scalar.math;
+
+import java.lang.Override;
+import java.lang.String;
+import org.elasticsearch.compute.data.Block;
+import org.elasticsearch.compute.data.DoubleBlock;
+import org.elasticsearch.compute.data.DoubleVector;
+import org.elasticsearch.compute.data.Page;
+import org.elasticsearch.compute.operator.EvalOperator;
+
+/**
+ * {@link EvalOperator.ExpressionEvaluator} implementation for {@link Tanh}.
+ * This class is generated. Do not edit it.
+ */
+public final class TanhEvaluator implements EvalOperator.ExpressionEvaluator {
+  private final EvalOperator.ExpressionEvaluator val;
+
+  public TanhEvaluator(EvalOperator.ExpressionEvaluator val) {
+    this.val = val;
+  }
+
+  @Override
+  public Block eval(Page page) {
+    Block valUncastBlock = val.eval(page);
+    if (valUncastBlock.areAllValuesNull()) {
+      return Block.constantNullBlock(page.getPositionCount());
+    }
+    DoubleBlock valBlock = (DoubleBlock) valUncastBlock;
+    DoubleVector valVector = valBlock.asVector();
+    if (valVector == null) {
+      return eval(page.getPositionCount(), valBlock);
+    }
+    return eval(page.getPositionCount(), valVector).asBlock();
+  }
+
+  public DoubleBlock eval(int positionCount, DoubleBlock valBlock) {
+    DoubleBlock.Builder result = DoubleBlock.newBlockBuilder(positionCount);
+    position: for (int p = 0; p < positionCount; p++) {
+      if (valBlock.isNull(p) || valBlock.getValueCount(p) != 1) {
+        result.appendNull();
+        continue position;
+      }
+      result.appendDouble(Tanh.process(valBlock.getDouble(valBlock.getFirstValueIndex(p))));
+    }
+    return result.build();
+  }
+
+  public DoubleVector eval(int positionCount, DoubleVector valVector) {
+    DoubleVector.Builder result = DoubleVector.newVectorBuilder(positionCount);
+    position: for (int p = 0; p < positionCount; p++) {
+      result.appendDouble(Tanh.process(valVector.getDouble(p)));
+    }
+    return result.build();
+  }
+
+  @Override
+  public String toString() {
+    return "TanhEvaluator[" + "val=" + val + "]";
+  }
+}

+ 12 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java

@@ -34,6 +34,8 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.date.Now;
 import org.elasticsearch.xpack.esql.expression.function.scalar.ip.CIDRMatch;
 import org.elasticsearch.xpack.esql.expression.function.scalar.math.Abs;
 import org.elasticsearch.xpack.esql.expression.function.scalar.math.AutoBucket;
+import org.elasticsearch.xpack.esql.expression.function.scalar.math.Cos;
+import org.elasticsearch.xpack.esql.expression.function.scalar.math.Cosh;
 import org.elasticsearch.xpack.esql.expression.function.scalar.math.E;
 import org.elasticsearch.xpack.esql.expression.function.scalar.math.Floor;
 import org.elasticsearch.xpack.esql.expression.function.scalar.math.IsFinite;
@@ -43,6 +45,10 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.math.Log10;
 import org.elasticsearch.xpack.esql.expression.function.scalar.math.Pi;
 import org.elasticsearch.xpack.esql.expression.function.scalar.math.Pow;
 import org.elasticsearch.xpack.esql.expression.function.scalar.math.Round;
+import org.elasticsearch.xpack.esql.expression.function.scalar.math.Sin;
+import org.elasticsearch.xpack.esql.expression.function.scalar.math.Sinh;
+import org.elasticsearch.xpack.esql.expression.function.scalar.math.Tan;
+import org.elasticsearch.xpack.esql.expression.function.scalar.math.Tanh;
 import org.elasticsearch.xpack.esql.expression.function.scalar.math.Tau;
 import org.elasticsearch.xpack.esql.expression.function.scalar.multivalue.MvAvg;
 import org.elasticsearch.xpack.esql.expression.function.scalar.multivalue.MvConcat;
@@ -91,6 +97,8 @@ public class EsqlFunctionRegistry extends FunctionRegistry {
             new FunctionDefinition[] {
                 def(Abs.class, Abs::new, "abs"),
                 def(AutoBucket.class, AutoBucket::new, "auto_bucket"),
+                def(Cos.class, Cos::new, "cos"),
+                def(Cosh.class, Cosh::new, "cosh"),
                 def(E.class, E::new, "e"),
                 def(Floor.class, Floor::new, "floor"),
                 def(IsFinite.class, IsFinite::new, "is_finite"),
@@ -100,6 +108,10 @@ public class EsqlFunctionRegistry extends FunctionRegistry {
                 def(Pi.class, Pi::new, "pi"),
                 def(Pow.class, Pow::new, "pow"),
                 def(Round.class, Round::new, "round"),
+                def(Sin.class, Sin::new, "sin"),
+                def(Sinh.class, Sinh::new, "sinh"),
+                def(Tan.class, Tan::new, "tan"),
+                def(Tanh.class, Tanh::new, "tanh"),
                 def(Tau.class, Tau::new, "tau") },
             // string
             new FunctionDefinition[] {

+ 60 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/AbstractTrigonometricFunction.java

@@ -0,0 +1,60 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.esql.expression.function.scalar.math;
+
+import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.esql.expression.function.scalar.UnaryScalarFunction;
+import org.elasticsearch.xpack.esql.planner.Mappable;
+import org.elasticsearch.xpack.ql.expression.Expression;
+import org.elasticsearch.xpack.ql.tree.Source;
+import org.elasticsearch.xpack.ql.type.DataType;
+import org.elasticsearch.xpack.ql.type.DataTypes;
+
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import static org.elasticsearch.xpack.ql.expression.TypeResolutions.ParamOrdinal.DEFAULT;
+import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isNumeric;
+
+/**
+ * Common base for trigonometric functions.
+ */
+abstract class AbstractTrigonometricFunction extends UnaryScalarFunction implements Mappable {
+    AbstractTrigonometricFunction(Source source, Expression field) {
+        super(source, field);
+    }
+
+    protected abstract EvalOperator.ExpressionEvaluator doubleEvaluator(EvalOperator.ExpressionEvaluator field);
+
+    @Override
+    public final Supplier<EvalOperator.ExpressionEvaluator> toEvaluator(
+        Function<Expression, Supplier<EvalOperator.ExpressionEvaluator>> toEvaluator
+    ) {
+        Supplier<EvalOperator.ExpressionEvaluator> fieldEval = Cast.cast(field().dataType(), DataTypes.DOUBLE, toEvaluator.apply(field()));
+        return () -> doubleEvaluator(fieldEval.get());
+    }
+
+    @Override
+    public final Object fold() {
+        return Mappable.super.fold();
+    }
+
+    @Override
+    protected final TypeResolution resolveType() {
+        if (childrenResolved() == false) {
+            return new TypeResolution("Unresolved children");
+        }
+
+        return isNumeric(field, sourceText(), DEFAULT);
+    }
+
+    @Override
+    public final DataType dataType() {
+        return DataTypes.DOUBLE;
+    }
+}

+ 45 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Cos.java

@@ -0,0 +1,45 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.esql.expression.function.scalar.math;
+
+import org.elasticsearch.compute.ann.Evaluator;
+import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.ql.expression.Expression;
+import org.elasticsearch.xpack.ql.tree.NodeInfo;
+import org.elasticsearch.xpack.ql.tree.Source;
+
+import java.util.List;
+
+/**
+ * Cosine trigonometric function.
+ */
+public class Cos extends AbstractTrigonometricFunction {
+    public Cos(Source source, Expression field) {
+        super(source, field);
+    }
+
+    @Override
+    protected EvalOperator.ExpressionEvaluator doubleEvaluator(EvalOperator.ExpressionEvaluator field) {
+        return new CosEvaluator(field);
+    }
+
+    @Override
+    public Expression replaceChildren(List<Expression> newChildren) {
+        return new Cos(source(), newChildren.get(0));
+    }
+
+    @Override
+    protected NodeInfo<? extends Expression> info() {
+        return NodeInfo.create(this, Cos::new, field());
+    }
+
+    @Evaluator
+    static double process(double val) {
+        return Math.cos(val);
+    }
+}

+ 45 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Cosh.java

@@ -0,0 +1,45 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.esql.expression.function.scalar.math;
+
+import org.elasticsearch.compute.ann.Evaluator;
+import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.ql.expression.Expression;
+import org.elasticsearch.xpack.ql.tree.NodeInfo;
+import org.elasticsearch.xpack.ql.tree.Source;
+
+import java.util.List;
+
+/**
+ * Cosine hyperbolic function.
+ */
+public class Cosh extends AbstractTrigonometricFunction {
+    public Cosh(Source source, Expression field) {
+        super(source, field);
+    }
+
+    @Override
+    protected EvalOperator.ExpressionEvaluator doubleEvaluator(EvalOperator.ExpressionEvaluator field) {
+        return new CoshEvaluator(field);
+    }
+
+    @Override
+    public Expression replaceChildren(List<Expression> newChildren) {
+        return new Cosh(source(), newChildren.get(0));
+    }
+
+    @Override
+    protected NodeInfo<? extends Expression> info() {
+        return NodeInfo.create(this, Cosh::new, field());
+    }
+
+    @Evaluator
+    static double process(double val) {
+        return Math.cosh(val);
+    }
+}

+ 45 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Sin.java

@@ -0,0 +1,45 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.esql.expression.function.scalar.math;
+
+import org.elasticsearch.compute.ann.Evaluator;
+import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.ql.expression.Expression;
+import org.elasticsearch.xpack.ql.tree.NodeInfo;
+import org.elasticsearch.xpack.ql.tree.Source;
+
+import java.util.List;
+
+/**
+ * Sine trigonometric function.
+ */
+public class Sin extends AbstractTrigonometricFunction {
+    public Sin(Source source, Expression field) {
+        super(source, field);
+    }
+
+    @Override
+    protected EvalOperator.ExpressionEvaluator doubleEvaluator(EvalOperator.ExpressionEvaluator field) {
+        return new SinEvaluator(field);
+    }
+
+    @Override
+    public Expression replaceChildren(List<Expression> newChildren) {
+        return new Sin(source(), newChildren.get(0));
+    }
+
+    @Override
+    protected NodeInfo<? extends Expression> info() {
+        return NodeInfo.create(this, Sin::new, field());
+    }
+
+    @Evaluator
+    static double process(double val) {
+        return Math.sin(val);
+    }
+}

+ 45 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Sinh.java

@@ -0,0 +1,45 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.esql.expression.function.scalar.math;
+
+import org.elasticsearch.compute.ann.Evaluator;
+import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.ql.expression.Expression;
+import org.elasticsearch.xpack.ql.tree.NodeInfo;
+import org.elasticsearch.xpack.ql.tree.Source;
+
+import java.util.List;
+
+/**
+ * Sine hyperbolic function.
+ */
+public class Sinh extends AbstractTrigonometricFunction {
+    public Sinh(Source source, Expression field) {
+        super(source, field);
+    }
+
+    @Override
+    protected EvalOperator.ExpressionEvaluator doubleEvaluator(EvalOperator.ExpressionEvaluator field) {
+        return new SinhEvaluator(field);
+    }
+
+    @Override
+    public Expression replaceChildren(List<Expression> newChildren) {
+        return new Sinh(source(), newChildren.get(0));
+    }
+
+    @Override
+    protected NodeInfo<? extends Expression> info() {
+        return NodeInfo.create(this, Sinh::new, field());
+    }
+
+    @Evaluator
+    static double process(double val) {
+        return Math.sinh(val);
+    }
+}

+ 45 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Tan.java

@@ -0,0 +1,45 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.esql.expression.function.scalar.math;
+
+import org.elasticsearch.compute.ann.Evaluator;
+import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.ql.expression.Expression;
+import org.elasticsearch.xpack.ql.tree.NodeInfo;
+import org.elasticsearch.xpack.ql.tree.Source;
+
+import java.util.List;
+
+/**
+ * Tangent trigonometric function.
+ */
+public class Tan extends AbstractTrigonometricFunction {
+    public Tan(Source source, Expression field) {
+        super(source, field);
+    }
+
+    @Override
+    protected EvalOperator.ExpressionEvaluator doubleEvaluator(EvalOperator.ExpressionEvaluator field) {
+        return new TanEvaluator(field);
+    }
+
+    @Override
+    public Expression replaceChildren(List<Expression> newChildren) {
+        return new Tan(source(), newChildren.get(0));
+    }
+
+    @Override
+    protected NodeInfo<? extends Expression> info() {
+        return NodeInfo.create(this, Tan::new, field());
+    }
+
+    @Evaluator
+    static double process(double val) {
+        return Math.tan(val);
+    }
+}

+ 45 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/Tanh.java

@@ -0,0 +1,45 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.esql.expression.function.scalar.math;
+
+import org.elasticsearch.compute.ann.Evaluator;
+import org.elasticsearch.compute.operator.EvalOperator;
+import org.elasticsearch.xpack.ql.expression.Expression;
+import org.elasticsearch.xpack.ql.tree.NodeInfo;
+import org.elasticsearch.xpack.ql.tree.Source;
+
+import java.util.List;
+
+/**
+ * Tangent hyperbolic function.
+ */
+public class Tanh extends AbstractTrigonometricFunction {
+    public Tanh(Source source, Expression field) {
+        super(source, field);
+    }
+
+    @Override
+    protected EvalOperator.ExpressionEvaluator doubleEvaluator(EvalOperator.ExpressionEvaluator field) {
+        return new TanhEvaluator(field);
+    }
+
+    @Override
+    public Expression replaceChildren(List<Expression> newChildren) {
+        return new Tanh(source(), newChildren.get(0));
+    }
+
+    @Override
+    protected NodeInfo<? extends Expression> info() {
+        return NodeInfo.create(this, Tanh::new, field());
+    }
+
+    @Evaluator
+    static double process(double val) {
+        return Math.tanh(val);
+    }
+}

+ 18 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/io/stream/PlanNamedTypes.java

@@ -44,6 +44,8 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.date.Now;
 import org.elasticsearch.xpack.esql.expression.function.scalar.ip.CIDRMatch;
 import org.elasticsearch.xpack.esql.expression.function.scalar.math.Abs;
 import org.elasticsearch.xpack.esql.expression.function.scalar.math.AutoBucket;
+import org.elasticsearch.xpack.esql.expression.function.scalar.math.Cos;
+import org.elasticsearch.xpack.esql.expression.function.scalar.math.Cosh;
 import org.elasticsearch.xpack.esql.expression.function.scalar.math.E;
 import org.elasticsearch.xpack.esql.expression.function.scalar.math.Floor;
 import org.elasticsearch.xpack.esql.expression.function.scalar.math.IsFinite;
@@ -53,6 +55,10 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.math.Log10;
 import org.elasticsearch.xpack.esql.expression.function.scalar.math.Pi;
 import org.elasticsearch.xpack.esql.expression.function.scalar.math.Pow;
 import org.elasticsearch.xpack.esql.expression.function.scalar.math.Round;
+import org.elasticsearch.xpack.esql.expression.function.scalar.math.Sin;
+import org.elasticsearch.xpack.esql.expression.function.scalar.math.Sinh;
+import org.elasticsearch.xpack.esql.expression.function.scalar.math.Tan;
+import org.elasticsearch.xpack.esql.expression.function.scalar.math.Tanh;
 import org.elasticsearch.xpack.esql.expression.function.scalar.math.Tau;
 import org.elasticsearch.xpack.esql.expression.function.scalar.multivalue.AbstractMultivalueFunction;
 import org.elasticsearch.xpack.esql.expression.function.scalar.multivalue.MvAvg;
@@ -271,12 +277,18 @@ public final class PlanNamedTypes {
             of(QL_UNARY_SCLR_CLS, IsNull.class, PlanNamedTypes::writeQLUnaryScalar, PlanNamedTypes::readQLUnaryScalar),
             of(QL_UNARY_SCLR_CLS, Not.class, PlanNamedTypes::writeQLUnaryScalar, PlanNamedTypes::readQLUnaryScalar),
             of(ESQL_UNARY_SCLR_CLS, Abs.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar),
+            of(ESQL_UNARY_SCLR_CLS, Cos.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar),
+            of(ESQL_UNARY_SCLR_CLS, Cosh.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar),
             of(ESQL_UNARY_SCLR_CLS, Floor.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar),
             of(ESQL_UNARY_SCLR_CLS, IsFinite.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar),
             of(ESQL_UNARY_SCLR_CLS, IsInfinite.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar),
             of(ESQL_UNARY_SCLR_CLS, IsNaN.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar),
             of(ESQL_UNARY_SCLR_CLS, Length.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar),
             of(ESQL_UNARY_SCLR_CLS, Log10.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar),
+            of(ESQL_UNARY_SCLR_CLS, Sin.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar),
+            of(ESQL_UNARY_SCLR_CLS, Sinh.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar),
+            of(ESQL_UNARY_SCLR_CLS, Tan.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar),
+            of(ESQL_UNARY_SCLR_CLS, Tanh.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar),
             of(ESQL_UNARY_SCLR_CLS, ToBoolean.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar),
             of(ESQL_UNARY_SCLR_CLS, ToDatetime.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar),
             of(ESQL_UNARY_SCLR_CLS, ToDouble.class, PlanNamedTypes::writeESQLUnaryScalar, PlanNamedTypes::readESQLUnaryScalar),
@@ -958,12 +970,18 @@ public final class PlanNamedTypes {
 
     static final Map<String, BiFunction<Source, Expression, UnaryScalarFunction>> ESQL_UNARY_SCALAR_CTRS = Map.ofEntries(
         entry(name(Abs.class), Abs::new),
+        entry(name(Cos.class), Cos::new),
+        entry(name(Cosh.class), Cosh::new),
         entry(name(Floor.class), Floor::new),
         entry(name(IsFinite.class), IsFinite::new),
         entry(name(IsInfinite.class), IsInfinite::new),
         entry(name(IsNaN.class), IsNaN::new),
         entry(name(Length.class), Length::new),
         entry(name(Log10.class), Log10::new),
+        entry(name(Sin.class), Sin::new),
+        entry(name(Sinh.class), Sinh::new),
+        entry(name(Tan.class), Tan::new),
+        entry(name(Tanh.class), Tanh::new),
         entry(name(ToBoolean.class), ToBoolean::new),
         entry(name(ToDatetime.class), ToDatetime::new),
         entry(name(ToDouble.class), ToDouble::new),

+ 53 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/CosTests.java

@@ -0,0 +1,53 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.esql.expression.function.scalar.math;
+
+import org.elasticsearch.xpack.esql.expression.function.scalar.AbstractScalarFunctionTestCase;
+import org.elasticsearch.xpack.ql.expression.Expression;
+import org.elasticsearch.xpack.ql.tree.Source;
+import org.elasticsearch.xpack.ql.type.DataType;
+import org.elasticsearch.xpack.ql.type.DataTypes;
+import org.hamcrest.Matcher;
+
+import java.util.List;
+
+import static org.hamcrest.Matchers.equalTo;
+
+public class CosTests extends AbstractScalarFunctionTestCase {
+    @Override
+    protected TestCase getSimpleTestCase() {
+        double d = 1 / randomDouble();
+        List<TypedData> typedData = List.of(new TypedData(d, DataTypes.DOUBLE, "arg"));
+        return new TestCase(Source.EMPTY, typedData, equalTo(Math.cos(d)));
+    }
+
+    @Override
+    protected DataType expectedType(List<DataType> argTypes) {
+        return DataTypes.DOUBLE;
+    }
+
+    @Override
+    protected Matcher<Object> resultMatcher(List<Object> data, DataType dataType) {
+        return equalTo(Math.cos(((Number) data.get(0)).doubleValue()));
+    }
+
+    @Override
+    protected String expectedEvaluatorSimpleToString() {
+        return "CosEvaluator[val=Attribute[channel=0]]";
+    }
+
+    @Override
+    protected List<ArgumentSpec> argSpec() {
+        return List.of(required(numerics()));
+    }
+
+    @Override
+    protected Expression build(Source source, List<Expression> args) {
+        return new Cos(source, args.get(0));
+    }
+}

+ 53 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/CoshTests.java

@@ -0,0 +1,53 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.esql.expression.function.scalar.math;
+
+import org.elasticsearch.xpack.esql.expression.function.scalar.AbstractScalarFunctionTestCase;
+import org.elasticsearch.xpack.ql.expression.Expression;
+import org.elasticsearch.xpack.ql.tree.Source;
+import org.elasticsearch.xpack.ql.type.DataType;
+import org.elasticsearch.xpack.ql.type.DataTypes;
+import org.hamcrest.Matcher;
+
+import java.util.List;
+
+import static org.hamcrest.Matchers.equalTo;
+
+public class CoshTests extends AbstractScalarFunctionTestCase {
+    @Override
+    protected TestCase getSimpleTestCase() {
+        double d = 1 / randomDouble();
+        List<TypedData> typedData = List.of(new TypedData(d, DataTypes.DOUBLE, "arg"));
+        return new TestCase(Source.EMPTY, typedData, equalTo(Math.cosh(d)));
+    }
+
+    @Override
+    protected DataType expectedType(List<DataType> argTypes) {
+        return DataTypes.DOUBLE;
+    }
+
+    @Override
+    protected Matcher<Object> resultMatcher(List<Object> data, DataType dataType) {
+        return equalTo(Math.cosh(((Number) data.get(0)).doubleValue()));
+    }
+
+    @Override
+    protected String expectedEvaluatorSimpleToString() {
+        return "CoshEvaluator[val=Attribute[channel=0]]";
+    }
+
+    @Override
+    protected List<ArgumentSpec> argSpec() {
+        return List.of(required(numerics()));
+    }
+
+    @Override
+    protected Expression build(Source source, List<Expression> args) {
+        return new Cosh(source, args.get(0));
+    }
+}

+ 53 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/SinTests.java

@@ -0,0 +1,53 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.esql.expression.function.scalar.math;
+
+import org.elasticsearch.xpack.esql.expression.function.scalar.AbstractScalarFunctionTestCase;
+import org.elasticsearch.xpack.ql.expression.Expression;
+import org.elasticsearch.xpack.ql.tree.Source;
+import org.elasticsearch.xpack.ql.type.DataType;
+import org.elasticsearch.xpack.ql.type.DataTypes;
+import org.hamcrest.Matcher;
+
+import java.util.List;
+
+import static org.hamcrest.Matchers.equalTo;
+
+public class SinTests extends AbstractScalarFunctionTestCase {
+    @Override
+    protected TestCase getSimpleTestCase() {
+        double d = 1 / randomDouble();
+        List<TypedData> typedData = List.of(new TypedData(d, DataTypes.DOUBLE, "arg"));
+        return new TestCase(Source.EMPTY, typedData, equalTo(Math.sin(d)));
+    }
+
+    @Override
+    protected DataType expectedType(List<DataType> argTypes) {
+        return DataTypes.DOUBLE;
+    }
+
+    @Override
+    protected Matcher<Object> resultMatcher(List<Object> data, DataType dataType) {
+        return equalTo(Math.sin(((Number) data.get(0)).doubleValue()));
+    }
+
+    @Override
+    protected String expectedEvaluatorSimpleToString() {
+        return "SinEvaluator[val=Attribute[channel=0]]";
+    }
+
+    @Override
+    protected List<ArgumentSpec> argSpec() {
+        return List.of(required(numerics()));
+    }
+
+    @Override
+    protected Expression build(Source source, List<Expression> args) {
+        return new Sin(source, args.get(0));
+    }
+}

+ 53 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/SinhTests.java

@@ -0,0 +1,53 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.esql.expression.function.scalar.math;
+
+import org.elasticsearch.xpack.esql.expression.function.scalar.AbstractScalarFunctionTestCase;
+import org.elasticsearch.xpack.ql.expression.Expression;
+import org.elasticsearch.xpack.ql.tree.Source;
+import org.elasticsearch.xpack.ql.type.DataType;
+import org.elasticsearch.xpack.ql.type.DataTypes;
+import org.hamcrest.Matcher;
+
+import java.util.List;
+
+import static org.hamcrest.Matchers.equalTo;
+
+public class SinhTests extends AbstractScalarFunctionTestCase {
+    @Override
+    protected TestCase getSimpleTestCase() {
+        double d = 1 / randomDouble();
+        List<TypedData> typedData = List.of(new TypedData(d, DataTypes.DOUBLE, "arg"));
+        return new TestCase(Source.EMPTY, typedData, equalTo(Math.sinh(d)));
+    }
+
+    @Override
+    protected DataType expectedType(List<DataType> argTypes) {
+        return DataTypes.DOUBLE;
+    }
+
+    @Override
+    protected Matcher<Object> resultMatcher(List<Object> data, DataType dataType) {
+        return equalTo(Math.sinh(((Number) data.get(0)).doubleValue()));
+    }
+
+    @Override
+    protected String expectedEvaluatorSimpleToString() {
+        return "SinhEvaluator[val=Attribute[channel=0]]";
+    }
+
+    @Override
+    protected List<ArgumentSpec> argSpec() {
+        return List.of(required(numerics()));
+    }
+
+    @Override
+    protected Expression build(Source source, List<Expression> args) {
+        return new Sinh(source, args.get(0));
+    }
+}

+ 53 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/TanTests.java

@@ -0,0 +1,53 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.esql.expression.function.scalar.math;
+
+import org.elasticsearch.xpack.esql.expression.function.scalar.AbstractScalarFunctionTestCase;
+import org.elasticsearch.xpack.ql.expression.Expression;
+import org.elasticsearch.xpack.ql.tree.Source;
+import org.elasticsearch.xpack.ql.type.DataType;
+import org.elasticsearch.xpack.ql.type.DataTypes;
+import org.hamcrest.Matcher;
+
+import java.util.List;
+
+import static org.hamcrest.Matchers.equalTo;
+
+public class TanTests extends AbstractScalarFunctionTestCase {
+    @Override
+    protected TestCase getSimpleTestCase() {
+        double d = 1 / randomDouble();
+        List<TypedData> typedData = List.of(new TypedData(d, DataTypes.DOUBLE, "arg"));
+        return new TestCase(Source.EMPTY, typedData, equalTo(Math.tan(d)));
+    }
+
+    @Override
+    protected DataType expectedType(List<DataType> argTypes) {
+        return DataTypes.DOUBLE;
+    }
+
+    @Override
+    protected Matcher<Object> resultMatcher(List<Object> data, DataType dataType) {
+        return equalTo(Math.tan(((Number) data.get(0)).doubleValue()));
+    }
+
+    @Override
+    protected String expectedEvaluatorSimpleToString() {
+        return "TanEvaluator[val=Attribute[channel=0]]";
+    }
+
+    @Override
+    protected List<ArgumentSpec> argSpec() {
+        return List.of(required(numerics()));
+    }
+
+    @Override
+    protected Expression build(Source source, List<Expression> args) {
+        return new Tan(source, args.get(0));
+    }
+}

+ 53 - 0
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/TanhTests.java

@@ -0,0 +1,53 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.esql.expression.function.scalar.math;
+
+import org.elasticsearch.xpack.esql.expression.function.scalar.AbstractScalarFunctionTestCase;
+import org.elasticsearch.xpack.ql.expression.Expression;
+import org.elasticsearch.xpack.ql.tree.Source;
+import org.elasticsearch.xpack.ql.type.DataType;
+import org.elasticsearch.xpack.ql.type.DataTypes;
+import org.hamcrest.Matcher;
+
+import java.util.List;
+
+import static org.hamcrest.Matchers.equalTo;
+
+public class TanhTests extends AbstractScalarFunctionTestCase {
+    @Override
+    protected TestCase getSimpleTestCase() {
+        double d = 1 / randomDouble();
+        List<TypedData> typedData = List.of(new TypedData(d, DataTypes.DOUBLE, "arg"));
+        return new TestCase(Source.EMPTY, typedData, equalTo(Math.tanh(d)));
+    }
+
+    @Override
+    protected DataType expectedType(List<DataType> argTypes) {
+        return DataTypes.DOUBLE;
+    }
+
+    @Override
+    protected Matcher<Object> resultMatcher(List<Object> data, DataType dataType) {
+        return equalTo(Math.tanh(((Number) data.get(0)).doubleValue()));
+    }
+
+    @Override
+    protected String expectedEvaluatorSimpleToString() {
+        return "TanhEvaluator[val=Attribute[channel=0]]";
+    }
+
+    @Override
+    protected List<ArgumentSpec> argSpec() {
+        return List.of(required(numerics()));
+    }
+
+    @Override
+    protected Expression build(Source source, List<Expression> args) {
+        return new Tanh(source, args.get(0));
+    }
+}