import { Comparer } from '@esfx/equatable' ; const binaryOperators = { "+" : add , "-" : sub , "*" : mul , "**" : pow , "/" : div , "%" : mod , "<<" : shl , ">>" : sar , ">>>" : shr , "&" : bitand , "|" : bitor , "^" : bitxor , "&&" : and , "||" : or , "??" : coalesce , "<" : lt , "<=" : le , ">" : gt , ">=" : ge , "==" : weq , "!=" : wne , "===" : eq , "!==" : ne , } ; const unaryOperators = { "+" : plus , "-" : neg , "~" : bitnot , "!" : not , } ; const unspecifiedOperators = { ... binaryOperators , ... unaryOperators , "+" : addOrPlus , "-" : subOrNeg , } ; export type BinaryOperators = typeof binaryOperators ; export type UnaryOperators = typeof unaryOperators ; export type Operators = typeof unspecifiedOperators ; export function operator < K extends keyof Operators > ( op ) ; export function operator < K extends keyof UnaryOperators > ( op , arity ) ; export function operator < K extends keyof BinaryOperators > ( op , arity ) ; export function operator < K extends keyof Operators > ( op , arity ? ) { const f = arity === 1 ? unaryOperators [ op as keyof UnaryOperators ] : arity === 2 ? binaryOperators [ op as keyof BinaryOperators ] : unspecifiedOperators [ op ] ; if ( ! f ) throw new TypeError ( "Invalid operator" ) ; return f ; } function addOrPlus ( x , y ) ; function addOrPlus ( x , y ) ; function addOrPlus ( x , y ) ; function addOrPlus ( x , y ) ; function addOrPlus ( x ) ; function addOrPlus ( x , y ? ) { return arguments . length === 1 ? plus ( x ) : add ( x , y ) ; } /**
 * Add/concat (i.e. `x + y`).
 */ export function add ( x , y ) ; export function add ( x , y ) ; export function add ( x , y ) ; export function add ( x , y ) ; export function add ( x , y ) { return x + y ; } function subOrNeg ( x , y ) ; function subOrNeg ( x , y ) ; function subOrNeg ( x ) ; function subOrNeg ( x ) ; function subOrNeg ( x , y ? ) { return arguments . length === 1 ? neg ( x ) : sub ( x , y ) ; } /**
 * Subtract (i.e. `x - y`).
 */ export function sub ( x , y ) ; export function sub ( x , y ) ; export function sub ( x , y ) { return x - y ; } /**
 * Multiply (i.e. `x * y`).
 */ export function mul ( x , y ) ; export function mul ( x , y ) ; export function mul ( x , y ) { return x * y ; } /**
 * Exponentiate (i.e. `x ** y`).
 */ export function pow ( x , y ) ; export function pow ( x , y ) ; export function pow ( x , y ) { return x ** y ; } /**
 * Divide (i.e. `x / y`).
 */ export function div ( x , y ) ; export function div ( x , y ) ; export function div ( x , y ) { return x / y ; } /**
 * Modulo (i.e. `x % y`).
 */ export function mod ( x , y ) ; export function mod ( x , y ) ; export function mod ( x , y ) { return x % y ; } /**
 * Left shift (i.e. `x << n`).
 */ export function shl ( x , n ) ; export function shl ( x , n ) ; export function shl ( x , n ) { return x << n ; } export { shl as sal } ; /**
 * Signed right shift (i.e. `x >> n`).
 */ export function sar ( x , n ) ; export function sar ( x , n ) ; export function sar ( x , n ) { return x >> n ; } /**
 * Unsigned right shift (i.e. `x >>> n`).
 */ export function shr ( x , n ) ; export function shr ( x , n ) ; export function shr ( x , n ) { return x >>> n ; } /**
 * Negate (i.e. `-x`).
 */ export function neg ( x ) ; export function neg ( x ) ; export function neg ( x ) { return - x ; } /**
 * Unary plus (i.e. `+x`).
 */ export function plus ( x ) { return + x ; } /**
 * Bitwise AND (i.e. `x & y`).
 */ export function bitand ( x , y ) ; export function bitand ( x , y ) ; export function bitand ( x , y ) { return x & y ; } /**
 * Bitwise OR (i.e. `x | y`).
 */ export function bitor ( x , y ) ; export function bitor ( x , y ) ; export function bitor ( x , y ) { return x | y ; } /**
 * Bitwise XOR (i.e. `x ^ y`).
 */ export function bitxor ( x , y ) ; export function bitxor ( x , y ) ; export function bitxor ( x , y ) { return x ^ y ; } /**
 * Bitwise NOT (i.e. `~x`).
 */ export function bitnot ( x ) ; export function bitnot ( x ) ; export function bitnot ( x ) { return ~ x ; } /**
 * Logical AND (i.e. `x && y`).
 */ export function and ( x , y ) { return x && y ; } /**
 * Logical OR (i.e. `x || y`).
 */ export function or ( x , y ) { return x || y ; } /**
 * Logical XOR (i.e. `x ? !y : y`).
 */ export function xor ( x , y ) { return x ? ! y : y ; } /**
 * Logical NOT (i.e. `!x`).
 */ export function not ( x ) { return ! x ; } /**
 * Nullish Coalesce (i.e. `x ?? y`).
 */ export function coalesce < T , U > ( x , y ) { return x !== undefined && x !== null ? x ! : y ; } /**
 * Relational greater-than (i.e. `x > y`).
 */ export function gt < T > ( x , y ) { return Comparer . defaultComparer . compare ( x , y ) > 0 ; } /**
 * Creates a copy of `gt` for a specific `Comparer`.
 */ gt . withComparer = < T > ( comparer ) : ( x : T , y : T ) => boolean => ( x , y ) => comparer . compare ( x , y ) > 0 ; /**
 * Relational greater-than-equals (i.e. `x >= y`).
 */ export function ge < T > ( x , y ) { return Comparer . defaultComparer . compare ( x , y ) >= 0 ; } /**
 * Creates a copy of `ge` for a specific `Comparer`.
 */ ge . withComparer = < T > ( comparer ) : ( x : T , y : T ) => boolean => ( x , y ) => comparer . compare ( x , y ) >= 0 ; /**
 * Relational less-than (i.e. `x < y`).
 */ export function lt < T > ( x , y ) { return Comparer . defaultComparer . compare ( x , y ) < 0 ; } /**
 * Creates a copy of `lt` for a specific `Comparer`.
 */ lt . withComparer = < T > ( comparer ) : ( x : T , y : T ) => boolean => ( x , y ) => comparer . compare ( x , y ) < 0 ; /**
 * Relational less-than-equals (i.e. `x <= y`).
 */ export function le < T > ( x , y ) { return Comparer . defaultComparer . compare ( x , y ) <= 0 ; } /**
 * Creates a copy of `le` for a specific `Comparer`.
 */ le . withComparer = < T > ( comparer ) : ( x : T , y : T ) => boolean => ( x , y ) => comparer . compare ( x , y ) <= 0 ; /**
 * Relational equals (i.e. `x >= y && x <= y`).
 */ export function req < T > ( x , y ) { return Comparer . defaultComparer . compare ( x , y ) === 0 ; } /**
 * Creates a copy of `eq` for a specific `Comparer`.
 */ req . withComparer = < T > ( comparer ) : ( x : T , y : T ) => boolean => ( x , y ) => comparer . compare ( x , y ) === 0 ; /**
 * Weak equality (i.e. `x == y`).
 */ export function weq < T > ( x , y ) { return x == y ; } /**
 * Strict equality (i.e. `x === y`).
 */ export function eq < T > ( x , y ) { return x === y ; } /**
 * Relational not-equals (i.e. `x < y || x > y`).
 */ export function rne < T > ( x , y ) { return Comparer . defaultComparer . compare ( x , y ) !== 0 ; } /**
 * Creates a copy of `ne` for a specific `Comparer`.
 */ rne . withComparer = < T > ( comparer ) : ( x : T , y : T ) => boolean => ( x , y ) => comparer . compare ( x , y ) !== 0 ; /**
 * Weak inequality (i.e. `x != y`).
 */ export function wne < T > ( x , y ) { return x != y ; } /**
 * Strict equality (i.e. `x !== y`).
 */ export function ne < T > ( x , y ) { return x !== y ; } /**
 * Relational minimum (i.e. `x <= y ? x : y`).
 */ export function min < T > ( x , y ) { return Comparer . defaultComparer . compare ( x , y ) <= 0 ? x : y ; } /**
 * Creates a copy of `min` for a specific `Comparer`.
 */ min . withComparer = < T > ( comparer ) : ( x : T , y : T ) => T => ( x , y ) => comparer . compare ( x , y ) <= 0 ? x : y ; /**
 * Relational minimum using a provided selector (i.e. `f(x) <= f(y) ? x : y`).
 */ export function minBy < T , K > ( x , y , f ) { return Comparer . defaultComparer . compare ( f ( x ) , f ( y ) ) <= 0 ? x : y ; } /**
 * Creates a copy of `minBy` for a specific `Comparer`.
 */ minBy . withComparer = < K > ( comparer ) : < T > ( x : T , y : T , f : ( v : T ) => K ) => T => ( x , y , f ) => comparer . compare ( f ( x ) , f ( y ) ) <= 0 ? x : y ; /**
 * Relational maximum (i.e. `x >= y ? x : y`).
 */ export function max < T > ( x , y ) { return Comparer . defaultComparer . compare ( x , y ) >= 0 ? x : y ; } /**
 * Creates a copy of `min` for a specific `Comparer`.
 */ max . withComparer = < K > ( comparer ) : ( x : K , y : K ) => K => ( x , y ) => comparer . compare ( x , y ) >= 0 ? x : y ; /**
 * Relational maximum using a provided selector (i.e. `f(x) <= f(y) ? x : y`).
 */ export function maxBy < T , K > ( x , y , f ) { return Comparer . defaultComparer . compare ( f ( x ) , f ( y ) ) >= 0 ? x : y ; } /**
 * Creates a copy of `maxBy` for a specific `Comparer`.
 */ maxBy . withComparer = < K > ( comparer ) : < T > ( x : T , y : T , f : ( v : T ) => K ) => T => ( x , y , f ) => comparer . compare ( f ( x ) , f ( y ) ) >= 0 ? x : y ;