Skip to content

Commit

Permalink
in memory PoC
Browse files Browse the repository at this point in the history
  • Loading branch information
radeusgd committed Feb 27, 2025
1 parent 8c72af1 commit a283f02
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,46 @@ from Standard.Base import all

import project.Column.Column
import project.Internal.Value_Type_Helpers
import project.Refined_Types.Numeric_Column.Numeric_Column
import project.Value_Type.Value_Type
from project.Internal.Type_Refinements.Single_Value_Column_Conversions import all
from project.Internal.Type_Refinements.Typed_Column_Conversions import all

refine_column (column : Column) =
## We treat a column as single value if it contains a single not-nothing value.
if is_single_value column . not then column else
inferred_value_type = column.inferred_precise_value_type
case inferred_value_type of
Value_Type.Integer _ ->
# `inferred_precise_value_type` will return Integer if the column was Float (or Mixed) but contained integral values - e.g. [2.0]
# We inspect the actual value to correctly deal with both Float and Mixed base type.
value = column.at 0
case value of
# If the value was really a float, we preserve that.
_ : Float -> (column : Column & Numeric_Column & Float)
# Otherwise we treat it as an integer.
_ -> (column : Column & Numeric_Column & Integer)
Value_Type.Float _ -> (column : Column & Numeric_Column & Float)
Value_Type.Char _ _ -> (column : Column & Text)
Value_Type.Boolean -> (column : Column & Boolean)
Value_Type.Date -> (column : Column & Date)
Value_Type.Time -> (column : Column & Time_Of_Day)
Value_Type.Date_Time True -> (column : Column & Date_Time)
Value_Type.Decimal _ _ ->
is_integer = Value_Type_Helpers.is_decimal_integer inferred_value_type
if is_integer then (column : Column & Numeric_Column & Integer) else (column : Column & Numeric_Column & Decimal)
# Other types (e.g. Mixed) are not supported.
_ -> column
if is_single_value column then _refine_single_value_column column else _refine_column column

private _refine_column column =
inferred_value_type = column.inferred_precise_value_type
case inferred_value_type of
Value_Type.Integer _ -> (column : Column & Numeric_Column)
Value_Type.Float _ -> (column : Column & Numeric_Column)
Value_Type.Decimal _ _ -> (column : Column & Numeric_Column)
_ -> column

private _refine_single_value_column column =
inferred_value_type = column.inferred_precise_value_type
case inferred_value_type of
Value_Type.Integer _ ->
# `inferred_precise_value_type` will return Integer if the column was Float (or Mixed) but contained integral values - e.g. [2.0]
# We inspect the actual value to correctly deal with both Float and Mixed base type.
value = column.at 0
case value of
# If the value was really a float, we preserve that.
_ : Float -> (column : Column & Numeric_Column & Float)
# Otherwise we treat it as an integer.
_ -> (column : Column & Numeric_Column & Integer)
Value_Type.Float _ -> (column : Column & Numeric_Column & Float)
Value_Type.Char _ _ -> (column : Column & Text)
Value_Type.Boolean -> (column : Column & Boolean)
Value_Type.Date -> (column : Column & Date)
Value_Type.Time -> (column : Column & Time_Of_Day)
Value_Type.Date_Time True -> (column : Column & Date_Time)
Value_Type.Decimal _ _ ->
is_integer = Value_Type_Helpers.is_decimal_integer inferred_value_type
if is_integer then (column : Column & Numeric_Column & Integer) else (column : Column & Numeric_Column & Decimal)
# Other types (e.g. Mixed) are not supported.
_ -> column

is_single_value column:Column -> Boolean =
(column.length == 1) && (column.at 0 . is_nothing . not)
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ from Standard.Base import all

import project.Column.Column
import project.Internal.Value_Type_Helpers
import project.Refined_Types.Numeric_Column.Numeric_Column
import project.Table.Table
import project.Value_Type.Value_Type
from project.Internal.Type_Refinements.Single_Column_Table_Conversions import all
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,30 @@
private

from Standard.Base import all
import Standard.Base.Errors.Illegal_Argument.Illegal_Argument

import project.Column.Column
import project.Internal.Type_Refinements.Typed_Column_Helpers
import project.Refined_Types.Numeric_Column.Numeric_Column
import project.Value_Type.Value_Type
from project.Column import apply_unary_operation, naming_helper

polyglot java import org.enso.table.data.column.operation.unary.AbsOperation
polyglot java import org.enso.table.data.column.operation.unary.SignumOperation

## This conversion is internal and should never be exported.
Numeric_Column.from (that : Column) =
...
if that.value_type.is_numeric.not then
Error.throw (Illegal_Argument.Error "Cannot convert a "+that.value_type.to_display_text+" column to a numeric column.")
Typed_Column_Helpers.make_numeric_column that In_Memory_Numeric_Column_Implementation

type In_Memory_Numeric_Column_Implementation
abs column =
Value_Type.expect_numeric column <|
new_name = naming_helper.concat ["abs", naming_helper.to_expression_text column]
apply_unary_operation column AbsOperation.INSTANCE new_name

signum column =
Value_Type.expect_numeric column <|
new_name = naming_helper.concat ["signum", naming_helper.to_expression_text column]
apply_unary_operation column SignumOperation.INSTANCE new_name
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import project.Refined_Types.Numeric_Column.Numeric_Column

## PRIVATE
For internal use only, this function should be used by implementations to
provide a hidden conversion to `Numeric_Column` that allows the type refinement.
make_numeric_column base_column numeric_operations_implementation =
Numeric_Column.Value base_column numeric_operations_implementation
2 changes: 2 additions & 0 deletions distribution/lib/Standard/Table/0.0.0-dev/src/Main.enso
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export project.Position.Position

export project.Prefix_Name.Prefix_Name

export project.Refined_Types.Numeric_Column.Numeric_Column

export project.Set_Mode.Set_Mode

export project.Simple_Expression.Simple_Calculation
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,31 @@
## A column that contains numeric values.
type Numeric_Column
private Value column operations_implementation

## GROUP Standard.Base.Operators
ICON operators
Computes the absolute value of each element in the column.

> Example
Compute the absolute value of values in a column.

import Standard.Examples

example_abs = Examples.decimal_column.abs
abs self -> Numeric_Column =
"TODO"
self.operations_implementation.abs self.column

## GROUP Standard.Base.Operators
ICON operators
Computes the sign of each element in the column.

It will return -1, 0 or 1 depending on the sign of the value.

> Example
Compute the signum of values in a column.

import Standard.Examples

example_signum = Examples.decimal_column.signum
signum self -> Numeric_Column =
"TODO"
self.operations_implementation.signum self.column
2 changes: 2 additions & 0 deletions test/Table_Tests/src/Common_Table_Operations/Main.enso
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import project.Common_Table_Operations.Map_Spec
import project.Common_Table_Operations.Map_To_Table_Spec
import project.Common_Table_Operations.Missing_Values_Spec
import project.Common_Table_Operations.Nothing_Spec
import project.Common_Table_Operations.Numeric_Column_Spec
import project.Common_Table_Operations.Offset_Spec
import project.Common_Table_Operations.Order_By_Spec
import project.Common_Table_Operations.Select_Columns_Spec
Expand Down Expand Up @@ -141,6 +142,7 @@ add_specs suite_builder setup =
Map_To_Table_Spec.add_specs suite_builder setup
Missing_Values_Spec.add_specs suite_builder setup
Nothing_Spec.add_specs suite_builder setup
Numeric_Column_Spec.add_specs suite_builder setup
Offset_Spec.add_specs suite_builder setup
Order_By_Spec.add_specs suite_builder setup
Replace_Spec.add_specs suite_builder setup
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from Standard.Base import all
import Standard.Base.Errors.Common.Type_Error

from Standard.Table import all
from Standard.Table.Errors import all

import Standard.Database.Feature.Feature

from Standard.Test import all

import project.Common_Table_Operations.Util
from project.Common_Table_Operations.Util import run_default_backend

type Lazy_Ref
Value ~get

main filter=Nothing = run_default_backend add_specs filter

add_specs suite_builder setup =
if setup.is_feature_supported Feature.Column_Operations then (add_numeric_columns_specs suite_builder setup)

add_numeric_columns_specs suite_builder setup =
prefix = setup.prefix
table_builder = setup.light_table_builder
build_sorted_table = Util.build_sorted_table setup
suite_builder.group prefix+"Numeric_Column" group_builder->
numeric_column = Lazy_Ref.Value <| build_sorted_table [["X", [-10, 0, 1, 12]]] . at "X"
group_builder.specify "a numeric column can be cast to Numeric_Column" <|
column = numeric_column.get
column.value_type.is_numeric . should_be_true
column:Numeric_Column

group_builder.specify "a text column cannot be cast to Numeric_Column" <|
column = table_builder [["X", ["txt"]]] . at "X"
column.value_type.is_numeric . should_be_false
Test.expect_panic Type_Error (column:Numeric_Column)

group_builder.specify "a numeric column supports abs operation" <|
column = numeric_column.get
abs_column = (column:Numeric_Column).abs
abs_column.to_vector . should_equal [10, 0, 1, 12]

group_builder.specify "a numeric column supports signum operation" <|
column = numeric_column.get
signum_column = (column:Numeric_Column).signum
signum_column.to_vector . should_equal [-1, 0, 1, 1]

group_builder.specify "floating-point columns support abs and signum" <|
column = build_sorted_table [["X", [-1.5, 0.0, -0.0, 1.0, 200.25]]] . at "X"
abs_column = (column:Numeric_Column).abs
abs_column.to_vector . should_equal [1.5, 0.0, 0.0, 1.0, 200.25]
signum_column = (column:Numeric_Column).signum
signum_column.to_vector . should_equal [-1, 0, 0, 1, 1]

group_builder.specify "a single value column can also be Numeric_Column" <|
column = table_builder [["X", [1]]] . at "X"
column:Numeric_Column

0 comments on commit a283f02

Please sign in to comment.