Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add EIP-5850: Complex Numbers stored in Bytes32 types #5850

Merged
merged 25 commits into from
Dec 14, 2022
Merged
Changes from 22 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions EIPS/eip-5850.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
eip: 5850
title: Complex Numbers stored in Bytes32 types
description: Store real and imaginary parts of complex numbers in the least significant and most significant 16 bytes respectively of a bytes32 type.
author: Paul Edge (@genkifs)
discussions-to: https://ethereum-magicians.org/t/eip-5850-store-real-and-imaginary-parts-of-complex-numbers-in-the-least-significant-and-most-significant-16-bytes-respectively-of-a-bytes32-type/11532
status: Draft
type: Standards Track
category: ERC
created: 2022-10-29
---

## Abstract

This EIP proposes a natural way for complex numbers to be stored in and retrieved from the bytes32 data-type. It splits the storage space exactly in half and, most importantly, assigns the real number part to the least significant 16 bytes and the imaginary number part to the most significant 16 bytes.

## Motivation
genkifs marked this conversation as resolved.
Show resolved Hide resolved

genkifs marked this conversation as resolved.
Show resolved Hide resolved
Complex numbers are an essential tool for many mathematical and scientific calculations. For example, Fourier Transforms, Characteristic functions, AC Circuits and Navier-Stokes equations all require the concept.

Complex numbers can be represented in many different forms (polynomial, cartesian, polar, exponential). The EIP creates a standard that can accomodate cartesian, polar and exponential formats with example code given for the Cartesian representation, where a complex number is just the pair of real numbers which gives the real and imaginary co-ordinates of the complex number. Equal storage capacity is assigned to both components and the order they appear is explicitly defined.

Packing complex numbers into a single bytes32 data object halves storage costs and creates a more natural code object that can be passed around the solidity ecosystem. Existing code may not need to be rewritten for complex numbers. For example, mappings by bytes32 are common and indexing in the 2D complex plane may improve code legibility.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, thank you for the EIP draft!

My question is regarding movitation: Could you help give more concrete examples of real world usage of on-chain imaginary numbers?

Also, is EIP/ERC the best place or is it better to be proposed as a Solidity/Vyper language feature?

@axic FYI

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you help give more concrete examples of real world usage of on-chain imaginary numbers?

Fundamentally, this EIP is essential if you want to track/control/record a variable (but more likely an array) that is complex in nature.

This EIP was focused on defining the storage aspect of the complex number building block, not how or why it would be manipulated on-chain. However, there is no harm discussing use cases outside of the EIP document.

  • Complex numbers are invaluable for electrical engineering specifications and calculations. A live certified safety standard defined as a working calculation (using the gasless view functionality) is much more valuable than a dead pdf equation.

  • Time-series analysis use Fourier Transforms for calculations and statistical distributions are defined via their complex number based characteristic function.

  • Linear algebra can easily enter into the realm of complex numbers.

  • Polynomials with non-real roots shouldn't necessarily interrupt your algorithm.

  • Code can be simpler, more readable and reusable if complex numbers are used (e.g. 2D rotations).

Even if you believe the above sorts of calculations will never be performed on-chain, some intermediate and final results will likely be reported as complex numbers.

But the simplest (and maybe most useful) use case/hack would be to define a 2d space within a single bytes32 data type.

proposed as a Solidity/Vyper language feature

Even though I gave the specification example in solidity, this EIP is language independent. The EVM stores data in 32 byte chunks. If we standardize that the least significant 16 bytes are Real and the most significant 16 bytes are Imaginary then any higher level language (Solidity/Vyper/etc.) can follow this implementation. If this were just a Solidity standard then other contracts written in Vyper would have difficulty understanding and interacting with these bytes32 objects.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think @xinbenlv's point was that this should be proposed as a feature either on the solidity or vyper (or both) repos. I think this could be an EIP, but the fact that it doesn't support floating point is a major hurdle to getting this adopted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be proposed as a feature either on the solidity or vyper (or both) repos

I believe this is at a language independent level, but as long as the standard is set with real numbers in the lower 16 bytes and imaginary numbers in the upper 16 bytes then I'm not that bothered where it lives.

the fact that it doesn't support floating point is a major hurdle

Neither fixed nor floating point are specified by the EIP. As currently defined, any number representation can be supported, so long as it fits inside the 16 bytes space.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As currently defined, any number representation can be supported, so long as it fits inside the 16 bytes space.

This was unclear when reading the EIP. I would highly suggest indicating this in the spec.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clarification added to the spec


Decimal numbers, either fix or floating, are not yet fully supported by Solidity so enforcing similar standards for complex versions is premature. However, it can be suggested that fixed point methods such as prb-math be used with 18 decimal places, or floating point methods like abdk.

## Specification

A complex number would be defined as Bytes32 and a cartesian representation would be initalized with the `cnNew` function and converted back with `RealIm`, both given below.

To create the complex number one would use

```solidity
function cnNew(int128 _Real, int128 _Imag) public pure returns (bytes32){
bytes32 Imag32 = bytes16(uint128(_Imag));
bytes32 Real32 = bytes16(uint128(_Real));
return (Real32>> 128) | Imag32;
}
```

and to convert back

```solidity
function RealIm(bytes32 _cn) public pure returns (int128 Real, int128 Imag){
bytes16[2] memory tmp = [bytes16(0), 0];
assembly {
mstore(tmp, _cn)
mstore(add(tmp, 16), _cn)
}
Imag=int128(uint128(tmp[0]));
Real=int128(uint128(tmp[1]));
}
```

## Rationale

An EIP is required as this proposal defines a complex numbers storage/type standard for multiple apps to use.

This EIP proposes to package both the real and imaginary within one existing data type, Bytes32. This allows compact storage without the need for structures and facilitates easy library implementations. The bytes32 would remain available for existing, non-complex number uses.
Only the split and position of the real & imaginary parts is defined in this EIP. Manipulation of complex numbers (addition, multiplication etc.), number of decimal places and other such topics are left for other EIP discussions. This keeps this EIP more focused and therfore more likely to succeed.

Defining real numbers in the 16 least-significant bytes allows direct conversion from `uint128` to `bytes32` for positive integers less than 2**127.
Direct conversion back from bytes32 -> uint -> int are not recommended as the complex number may contain imaginary parts and/or the real part may be negative. It is better to always use `RealIm` for separating the complex part.

Libraries for complex number manipulation can be implemented with the `Using Complex for bytes32` syntax where `Complex` would be the name of the library.

## Backwards Compatibility

There is no impact on other uses of the `bytes32` datatype.

## Security Considerations

If complex numbers are manipulated in bytes32 form then overflow checks must be performed manually during the manipulation.

## Copyright

Copyright and related rights waived via [CC0](../LICENSE.md).